diff --git a/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.cpp b/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.cpp index 335c1fd11f..2d5b96caa7 100644 --- a/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.cpp +++ b/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.cpp @@ -1,73 +1,138 @@ /*=================================================================== 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 "mitkNavigationDataDisplacementFilter.h" #include "mitkPropertyList.h" #include "mitkProperties.h" mitk::NavigationDataDisplacementFilter::NavigationDataDisplacementFilter() -: mitk::NavigationDataToNavigationDataFilter() +: mitk::NavigationDataToNavigationDataFilter(), m_Transform6DOF(false) { m_Offset[0] = 0.0; m_Offset[1] = 0.0; m_Offset[2] = 0.0; + + m_Transformation = mitk::NavigationData::New(); + } mitk::NavigationDataDisplacementFilter::~NavigationDataDisplacementFilter() { } void mitk::NavigationDataDisplacementFilter::GenerateData() { /* update outputs with tracking data from tools */ - for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i) + if( !m_Transform6DOF ) + { + for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i) + { + mitk::NavigationData* output = this->GetOutput(i); + assert(output); + const mitk::NavigationData* input = this->GetInput(i); + assert(input); + + if (input->IsDataValid() == false) + { + output->SetDataValid(false); + continue; + } + output->Graft(input); // First, copy all information from input to output + output->SetPosition(input->GetPosition() + m_Offset); // Then change the member(s): add offset to position of navigation data + output->SetDataValid(true); // operation was successful, therefore data of output is valid. + // don't change anything else here + } + } + else { - mitk::NavigationData* output = this->GetOutput(i); - assert(output); - const mitk::NavigationData* input = this->GetInput(i); - assert(input); + if( this->GetNumberOfOutputs() < 2 ) + { + MITK_WARN << "TrackedUltrasound not possible. The number of tracked devices must be at least 2."; + return; + } + + //important: First device = Needle | Second device = US-Tracker + + mitk::NavigationData::Pointer needleOut = this->GetOutput(0); + const mitk::NavigationData* needleIn = this->GetInput(0); + + mitk::NavigationData::Pointer usTrackerOut = this->GetOutput(1); + const mitk::NavigationData* usTrackerIn = this->GetInput(1); - if (input->IsDataValid() == false) + if(needleIn->IsDataValid() == false ) { - output->SetDataValid(false); - continue; + needleOut->SetDataValid(false); + } + else + needleOut->Graft(needleIn); + + if (usTrackerIn->IsDataValid() == false) + { + usTrackerOut->SetDataValid(false); + } + else + usTrackerOut->Graft(usTrackerIn); + + needleOut->Compose( usTrackerOut->GetInverse(), false ); + needleOut->Compose( m_Transformation->GetInverse() ); + + usTrackerOut->SetDataValid(true); + needleOut->SetDataValid(true); + + if( this->GetNumberOfOutputs() > 2 ) + { + for( unsigned int i = 2; i < this->GetNumberOfOutputs(); ++i ) + { + mitk::NavigationData* output = this->GetOutput(i); + const mitk::NavigationData* input = this->GetInput(i); + + if (input->IsDataValid() == false) + { + output->SetDataValid(false); + continue; + } + output->Graft(input); + output->SetDataValid(true); + } } - output->Graft(input); // First, copy all information from input to output - output->SetPosition(input->GetPosition() + m_Offset); // Then change the member(s): add offset to position of navigation data - output->SetDataValid(true); // operation was successful, therefore data of output is valid. - // don't change anything else here } } +void mitk::NavigationDataDisplacementFilter::SetTransformation(mitk::AffineTransform3D::Pointer transform) +{ + mitk::NavigationData::Pointer transformation = mitk::NavigationData::New(transform); + m_Transformation = transformation; +} + void mitk::NavigationDataDisplacementFilter::SetParameters( const mitk::PropertyList* p ) { if (p == nullptr) return; mitk::Vector3D v; if (p->GetPropertyValue("NavigationDataDisplacementFilter_Offset", v) == true) // search for Offset parameter this->SetOffset(v); // apply if found; } mitk::PropertyList::ConstPointer mitk::NavigationDataDisplacementFilter::GetParameters() const { mitk::PropertyList::Pointer p = mitk::PropertyList::New(); p->SetProperty("NavigationDataDisplacementFilter_Offset", mitk::Vector3DProperty::New(this->GetOffset())); // store Offset parameter return mitk::PropertyList::ConstPointer(p); } diff --git a/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.h b/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.h index e5dfba4422..d1ae1695a4 100644 --- a/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.h +++ b/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.h @@ -1,76 +1,85 @@ /*=================================================================== 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 MITKNavigationDataDisplacementFilter_H_HEADER_INCLUDED_ #define MITKNavigationDataDisplacementFilter_H_HEADER_INCLUDED_ #include namespace mitk { /**Documentation * \brief NavigationDataDisplacementFilter adds an offset to navigation data objects * * Example class that shows how to write a navigation filter. This filter * adds a offset that can be specified as a parameter to each input navigation data. * * \ingroup IGT */ class MITKIGT_EXPORT NavigationDataDisplacementFilter : public NavigationDataToNavigationDataFilter { public: mitkClassMacro(NavigationDataDisplacementFilter, NavigationDataToNavigationDataFilter); itkFactorylessNewMacro(Self) itkCloneMacro(Self) mitkSetVectorMacro(Offset, mitk::Vector3D); ///< Get Offset parameter mitkGetVectorMacro(Offset, mitk::Vector3D); ///< Set Offset parameter + itkSetMacro(Transform6DOF, bool); + itkGetMacro(Transform6DOF, bool); + + void SetTransformation( mitk::AffineTransform3D::Pointer transform ); /** *\brief Set all filter parameters (Offset) as the PropertyList p * * This method reads the following properties from the PropertyList (name : data type): * - "NavigationDataDisplacementFilter_Offset" : mitk::Vector3DProperty */ void SetParameters(const mitk::PropertyList* p) override; /** *\brief Get all filter parameters (offset) as a PropertyList * * This method returns a PropertyList containing the following * properties (name : data type): * - "NavigationDataDisplacementFilter_Offset" : mitk::Vector3DProperty * The returned PropertyList must be assigned to a * SmartPointer immediately, or else it will get destroyed. */ mitk::PropertyList::ConstPointer GetParameters() const override; protected: NavigationDataDisplacementFilter(); ~NavigationDataDisplacementFilter() override; /**Documentation * \brief filter execute method * * adds the offset m_Offset to all inputs */ void GenerateData() override; mitk::Vector3D m_Offset; ///< offset that is added to all inputs + + bool m_Transform6DOF; + + mitk::NavigationData::Pointer m_Transformation; + }; } // namespace mitk #endif /* MITKNAVIGATIONDATATONAVIGATIONDATAFILTER_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp b/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp index a8a56365c0..7ebe9b002c 100644 --- a/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp +++ b/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp @@ -1,156 +1,169 @@ /*=================================================================== 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 "mitkNavigationDataSource.h" #include "mitkUIDGenerator.h" //Microservices #include #include #include #include const std::string mitk::NavigationDataSource::US_INTERFACE_NAME = "org.mitk.services.NavigationDataSource"; const std::string mitk::NavigationDataSource::US_PROPKEY_DEVICENAME = US_INTERFACE_NAME + ".devicename"; const std::string mitk::NavigationDataSource::US_PROPKEY_ID = US_INTERFACE_NAME + ".id"; const std::string mitk::NavigationDataSource::US_PROPKEY_ISACTIVE = US_INTERFACE_NAME + ".isActive"; mitk::NavigationDataSource::NavigationDataSource() -: itk::ProcessObject(), m_Name("NavigationDataSource (no defined type)"), m_IsFrozen(false) +: itk::ProcessObject(), m_Name("NavigationDataSource (no defined type)"), m_IsFrozen(false), m_ToolMetaDataCollection(mitk::NavigationToolStorage::New()) { } mitk::NavigationDataSource::~NavigationDataSource() { } mitk::NavigationData* mitk::NavigationDataSource::GetOutput() { if (this->GetNumberOfIndexedOutputs() < 1) return nullptr; return static_cast(this->ProcessObject::GetPrimaryOutput()); } mitk::NavigationData* mitk::NavigationDataSource::GetOutput(DataObjectPointerArraySizeType idx) { NavigationData* out = dynamic_cast( this->ProcessObject::GetOutput(idx) ); if ( out == nullptr && this->ProcessObject::GetOutput(idx) != nullptr ) { itkWarningMacro (<< "Unable to convert output number " << idx << " to type " << typeid( NavigationData ).name () ); } return out; } mitk::NavigationData* mitk::NavigationDataSource::GetOutput(const std::string& navDataName) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::iterator it = outputs.begin(); it != outputs.end(); ++it) if (navDataName == (static_cast(it->GetPointer()))->GetName()) return static_cast(it->GetPointer()); return nullptr; } itk::ProcessObject::DataObjectPointerArraySizeType mitk::NavigationDataSource::GetOutputIndex( std::string navDataName ) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::size_type i = 0; i < outputs.size(); ++i) if (navDataName == (static_cast(outputs.at(i).GetPointer()))->GetName()) return i; throw std::invalid_argument("output name does not exist"); } void mitk::NavigationDataSource::RegisterAsMicroservice(){ // Get Context us::ModuleContext* context = us::GetModuleContext(); // Define ServiceProps us::ServiceProperties props; mitk::UIDGenerator uidGen = mitk::UIDGenerator ("org.mitk.services.NavigationDataSource.id_", 16); props[ US_PROPKEY_ID ] = uidGen.GetUID(); props[ US_PROPKEY_DEVICENAME ] = m_Name; m_ServiceRegistration = context->RegisterService(this, props); } void mitk::NavigationDataSource::UnRegisterMicroservice(){ if (m_ServiceRegistration != nullptr) m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } std::string mitk::NavigationDataSource::GetMicroserviceID(){ return this->m_ServiceRegistration.GetReference().GetProperty(US_PROPKEY_ID).ToString(); } void mitk::NavigationDataSource::GraftOutput(itk::DataObject *graft) { this->GraftNthOutput(0, graft); } void mitk::NavigationDataSource::GraftNthOutput(unsigned int idx, itk::DataObject *graft) { if ( idx >= this->GetNumberOfIndexedOutputs() ) { itkExceptionMacro(<<"Requested to graft output " << idx << " but this filter only has " << this->GetNumberOfIndexedOutputs() << " Outputs."); } if ( !graft ) { itkExceptionMacro(<<"Requested to graft output with a nullptr pointer object" ); } itk::DataObject* output = this->GetOutput(idx); if ( !output ) { itkExceptionMacro(<<"Requested to graft output that is a nullptr pointer" ); } // Call Graft on NavigationData to copy member data output->Graft( graft ); } itk::DataObject::Pointer mitk::NavigationDataSource::MakeOutput ( DataObjectPointerArraySizeType /*idx*/ ) { return mitk::NavigationData::New().GetPointer(); } itk::DataObject::Pointer mitk::NavigationDataSource::MakeOutput( const DataObjectIdentifierType & name ) { itkDebugMacro("MakeOutput(" << name << ")"); if( this->IsIndexedOutputName(name) ) { return this->MakeOutput( this->MakeIndexFromOutputName(name) ); } return static_cast(mitk::NavigationData::New().GetPointer()); } mitk::PropertyList::ConstPointer mitk::NavigationDataSource::GetParameters() const { mitk::PropertyList::Pointer p = mitk::PropertyList::New(); // add properties to p like this: //p->SetProperty("MyFilter_MyParameter", mitk::PropertyDataType::New(m_MyParameter)); return mitk::PropertyList::ConstPointer(p); } void mitk::NavigationDataSource::Freeze() { m_IsFrozen = true; } void mitk::NavigationDataSource::UnFreeze() { m_IsFrozen = false; } + +mitk::NavigationTool::Pointer mitk::NavigationDataSource::GetToolMetaData(DataObjectPointerArraySizeType idx) +{ + if (idx >= this->GetNumberOfIndexedOutputs()) { return mitk::NavigationTool::New(); } + else { return GetToolMetaData(this->GetOutput(idx)->GetName()); } +} + +mitk::NavigationTool::Pointer mitk::NavigationDataSource::GetToolMetaData(const std::string& navDataName) +{ + mitk::NavigationTool::Pointer returnValue = m_ToolMetaDataCollection->GetToolByName(navDataName); + if (returnValue == nullptr) { returnValue = mitk::NavigationTool::New(); } + return returnValue; +} diff --git a/Modules/IGT/DataManagement/mitkNavigationDataSource.h b/Modules/IGT/DataManagement/mitkNavigationDataSource.h index 206c544f2f..c1d8963286 100644 --- a/Modules/IGT/DataManagement/mitkNavigationDataSource.h +++ b/Modules/IGT/DataManagement/mitkNavigationDataSource.h @@ -1,186 +1,214 @@ /*=================================================================== 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 MITKNAVIGATIONDATASOURCE_H_HEADER_INCLUDED_ #define MITKNAVIGATIONDATASOURCE_H_HEADER_INCLUDED_ #include #include "mitkNavigationData.h" +#include +#include #include "mitkPropertyList.h" #include "MitkIGTExports.h" // Microservices #include #include namespace mitk { /**Documentation * \brief Navigation Data source * * Base class for all navigation filters that produce NavigationData objects as output. * This class defines the output-interface for NavigationDataFilters. * \warning: if Update() is called on any output object, all NavigationData filters will * generate new output data for all outputs, not just the one on which Update() was called. * * \ingroup IGT */ class MITKIGT_EXPORT NavigationDataSource : public itk::ProcessObject { public: mitkClassMacroItkParent(NavigationDataSource, itk::ProcessObject); /** @return Returns a human readable name of this source. There will be a default name, * or you can set the name with the method SetName() if you want to change it. */ itkGetMacro(Name,std::string); /** @brief Sets the human readable name of this source. There is also a default name, * but you can use this method if you need to define it on your own. */ itkSetMacro(Name,std::string); /** *\brief return the output (output with id 0) of the filter */ NavigationData* GetOutput(void); /** *\brief return the output with id idx of the filter */ NavigationData* GetOutput(DataObjectPointerArraySizeType idx); /** *\brief return the output with name navDataName of the filter */ NavigationData* GetOutput(const std::string& navDataName); + /** @return Returns the metadata of the navigation tool at + * the given idx. Returns an empty object if no + * metadata is available. + */ + NavigationTool::Pointer GetToolMetaData(DataObjectPointerArraySizeType idx); + + /** @return Returns the metadata of the navigation tool with + * the given name. Returns an empty object if no + * metadata is available. + */ + NavigationTool::Pointer GetToolMetaData(const std::string& navDataName); + + /** @return Returns the metadata of all tools identified by the tool name. + * There is no need to set the metadata of the tools, so not + * every tool has metadata available. Returns an empty tool storage + * if no metadata was set at all.*/ + itkGetMacro(ToolMetaDataCollection, mitk::NavigationToolStorage::Pointer); + + /** Sets the tool metadata as NavigationToolStorage object. */ + itkSetMacro(ToolMetaDataCollection, mitk::NavigationToolStorage::Pointer); + /** *\brief return the index of the output with name navDataName, -1 if no output with that name was found * * \warning if a subclass has outputs that have different data type than mitk::NavigationData, they have to overwrite this method */ DataObjectPointerArraySizeType GetOutputIndex(std::string navDataName); /** *\brief Registers this object as a Microservice, making it available to every module and/or plugin. * To unregister, call UnregisterMicroservice(). */ virtual void RegisterAsMicroservice(); /** *\brief Registers this object as a Microservice, making it available to every module and/or plugin. */ virtual void UnRegisterMicroservice(); /** *\brief Returns the id that this device is registered with. The id will only be valid, if the * NavigationDataSource has been registered using RegisterAsMicroservice(). */ std::string GetMicroserviceID(); /** *\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_ID; static const std::string US_PROPKEY_ISACTIVE; //NOT IMPLEMENTED YET! /** *\brief Graft the specified DataObject onto this ProcessObject's output. * * See itk::ImageSource::GraftNthOutput for details */ virtual void GraftNthOutput(unsigned int idx, itk::DataObject *graft); /** * \brief Graft the specified DataObject onto this ProcessObject's output. * * See itk::ImageSource::Graft Output for details */ virtual void GraftOutput(itk::DataObject *graft); /** * Allocates a new output object and returns it. Currently the * index idx is not evaluated. * @param idx the index of the output for which an object should be created * @returns the new object */ itk::DataObject::Pointer MakeOutput ( DataObjectPointerArraySizeType idx ) override; /** * This is a default implementation to make sure we have something. * Once all the subclasses of ProcessObject provide an appopriate * MakeOutput(), then ProcessObject::MakeOutput() can be made pure * virtual. */ itk::DataObject::Pointer MakeOutput(const DataObjectIdentifierType &name) override; /** * \brief Set all filter parameters as the PropertyList p * * This method allows to set all parameters of a filter with one * method call. For the names of the parameters, take a look at * the GetParameters method of the filter * This method has to be overwritten by each MITK-IGT filter. */ virtual void SetParameters(const mitk::PropertyList*){}; /** * \brief Get all filter parameters as a PropertyList * * This method allows to get all parameters of a filter with one * method call. The returned PropertyList must be assigned to a * SmartPointer immediately, or else it will get destroyed. * Every filter must overwrite this method to create a filter-specific * PropertyList. Note that property names must be unique over all * MITK-IGT filters. Therefore each filter should use its name as a prefix * for each property name. * Secondly, each filter should list the property names and data types * in the method documentation. */ virtual mitk::PropertyList::ConstPointer GetParameters() const; /** Freezes the navigation data source which means the current state is frozen and the output * navigation data stays at it is. Calling Update() does not have any effect until UnFreeze() * is called. This also means that the data source is not updated any more. */ virtual void Freeze(); /** Unfreezes the data source. */ virtual void UnFreeze(); /** @return Returns whether the data source is currently frozen. */ itkGetMacro(IsFrozen,bool); protected: NavigationDataSource(); ~NavigationDataSource() override; std::string m_Name; bool m_IsFrozen; + /** Holds the metadata of all tools identified by the tool name. + * There is no need to set the metadata of the tools, so not + * every tool has metadata available. */ + NavigationToolStorage::Pointer m_ToolMetaDataCollection; + private: us::ServiceRegistration m_ServiceRegistration; }; } // namespace mitk // This is the microservice declaration. Do not meddle! MITK_DECLARE_SERVICE_INTERFACE(mitk::NavigationDataSource, "org.mitk.services.NavigationDataSource") #endif /* MITKNAVIGATIONDATASOURCE_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidgetControls.ui index 6daf485458..659f57055c 100644 --- a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidgetControls.ui @@ -1,463 +1,463 @@ QmitkInteractiveTransformationWidgetControls 0 0 435 381 Form Interactive Translation 50 false x-Direction (Frontal): false 0 0 ArrowCursor -500 500 1 Qt::Horizontal false false QSlider::TicksAbove 100 - 1 + 4 -500.000000000000000 500.000000000000000 50 false y-Direction (Sagittal): false 0 0 -500 500 Qt::Horizontal false QSlider::TicksAbove 100 - 1 + 4 -500.000000000000000 500.000000000000000 50 false z-Direction (Transversal): false 0 0 -500 500 0 Qt::Horizontal false QSlider::TicksAbove 100 - 1 + 4 -500.000000000000000 500.000000000000000 Interactive Rotation 50 false x-Axis (Frontal): false 0 0 ArrowCursor -180 180 Qt::Horizontal QSlider::TicksAbove 45 - 1 + 4 -180.000000000000000 180.000000000000000 50 false y-Axis (Sagittal): false 0 0 -180 180 Qt::Horizontal QSlider::TicksAbove 45 - 1 + 4 -180.000000000000000 180.000000000000000 50 false z-Axis (Transversal): false 0 0 -180 180 Qt::Horizontal QSlider::TicksAbove 45 - 1 + 4 -180.000000000000000 180.000000000000000 Use Manipulated ToolTip Reset To Identity Revert Changes Cancel diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp index 0419e4ca9e..d1adf13a79 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp @@ -1,137 +1,134 @@ /*=================================================================== 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 "QmitkNavigationDataSourceSelectionWidget.h" //mitk headers #include #include #include QmitkNavigationDataSourceSelectionWidget::QmitkNavigationDataSourceSelectionWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = nullptr; CreateQtPartControl(this); CreateConnections(); } QmitkNavigationDataSourceSelectionWidget::~QmitkNavigationDataSourceSelectionWidget() { } void QmitkNavigationDataSourceSelectionWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNavigationDataSourceSelectionWidgetControls; m_Controls->setupUi(parent); std::string empty = ""; m_Controls->m_NavigationDataSourceWidget->Initialize(mitk::NavigationDataSource::US_PROPKEY_DEVICENAME,empty); } } void QmitkNavigationDataSourceSelectionWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_NavigationDataSourceWidget), SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(NavigationDataSourceSelected(us::ServiceReferenceU)) ); connect((QObject*)(m_Controls->m_ToolView), SIGNAL(currentRowChanged(int)), this, SLOT(NavigationToolSelected(int))); } } void QmitkNavigationDataSourceSelectionWidget::NavigationToolSelected(int selection) { emit NavigationToolSelected(this->m_CurrentStorage->GetTool(selection)); } void QmitkNavigationDataSourceSelectionWidget::NavigationDataSourceSelected(us::ServiceReferenceU s) { if (!s) //no device selected { //reset everything m_CurrentSource = nullptr; m_CurrentStorage = nullptr; emit NavigationDataSourceSelected(m_CurrentSource); return; } // Get Source us::ModuleContext* context = us::GetModuleContext(); m_CurrentSource = context->GetService(s); // clear tool list before filling it m_Controls->m_ToolView->clear(); //Fill tool list MITK_INFO<<"no outputs: "<GetNumberOfOutputs(); for(std::size_t i = 0; i < m_CurrentSource->GetNumberOfOutputs(); i++) { new QListWidgetItem(tr(m_CurrentSource->GetOutput(i)->GetName()), m_Controls->m_ToolView); } - // Get Storage - std::string filter = "(" + mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID + "=" + m_CurrentSource->GetMicroserviceID() + ")"; - std::vector > refs = context->GetServiceReferences(filter); - if (refs.empty()) return; //no storage was found - m_CurrentStorage = context->GetService(refs.front()); + // Get corresponding tool storage + m_CurrentStorage = m_CurrentSource->GetToolMetaDataCollection(); if (m_CurrentStorage.IsNull()) { MITK_WARN << "Found an invalid storage object!"; return; } if (m_CurrentStorage->GetToolCount() != m_CurrentSource->GetNumberOfOutputs()) //there is something wrong with the storage { MITK_WARN << "Found a tool storage, but it has not the same number of tools like the NavigationDataSource. This storage won't be used because it isn't the right one."; m_CurrentStorage = nullptr; } emit NavigationDataSourceSelected(m_CurrentSource); } mitk::NavigationDataSource::Pointer QmitkNavigationDataSourceSelectionWidget::GetSelectedNavigationDataSource() { return this->m_CurrentSource; } int QmitkNavigationDataSourceSelectionWidget::GetSelectedToolID() { return this->m_Controls->m_ToolView->currentIndex().row(); } mitk::NavigationTool::Pointer QmitkNavigationDataSourceSelectionWidget::GetSelectedNavigationTool() { if (this->m_CurrentStorage.IsNull()) return nullptr; if ((m_Controls->m_ToolView->currentIndex().row() < 0) || (static_cast(m_Controls->m_ToolView->currentIndex().row()) >= m_CurrentStorage->GetToolCount())) return nullptr; return this->m_CurrentStorage->GetTool(m_Controls->m_ToolView->currentIndex().row()); } mitk::NavigationToolStorage::Pointer QmitkNavigationDataSourceSelectionWidget::GetNavigationToolStorageOfSource() { return this->m_CurrentStorage; } diff --git a/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp b/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp index 5a9a1bbfa3..a127c17e19 100644 --- a/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp +++ b/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp @@ -1,200 +1,202 @@ /*=================================================================== 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 "mitkIGTLMessageSource.h" #include "mitkUIDGenerator.h" //Microservices #include #include #include #include const std::string mitk::IGTLMessageSource::US_INTERFACE_NAME = "org.mitk.services.IGTLMessageSource"; const std::string mitk::IGTLMessageSource::US_PROPKEY_DEVICENAME = US_INTERFACE_NAME + ".devicename"; const std::string mitk::IGTLMessageSource::US_PROPKEY_DEVICETYPE = US_INTERFACE_NAME + ".devicetype"; const std::string mitk::IGTLMessageSource::US_PROPKEY_ID = US_INTERFACE_NAME + ".id"; const std::string mitk::IGTLMessageSource::US_PROPKEY_ISACTIVE = US_INTERFACE_NAME + ".isActive"; mitk::IGTLMessageSource::IGTLMessageSource() : itk::ProcessObject(), m_Name("IGTLMessageSource (no defined type)"), m_Type("NONE"), m_StreamingFPS(0) { m_StreamingFPSMutex = itk::FastMutexLock::New(); } mitk::IGTLMessageSource::~IGTLMessageSource() { //this->UnRegisterMicroservice(); } mitk::IGTLMessage* mitk::IGTLMessageSource::GetOutput() { if (this->GetNumberOfIndexedOutputs() < 1) { MITK_WARN << "IGTLMessageSource contained no outputs. Returning nullptr."; return nullptr; } return static_cast(this->ProcessObject::GetPrimaryOutput()); } mitk::IGTLMessage* mitk::IGTLMessageSource::GetOutput( DataObjectPointerArraySizeType idx) { IGTLMessage* out = dynamic_cast( this->ProcessObject::GetOutput(idx) ); if ( out == nullptr && this->ProcessObject::GetOutput(idx) != nullptr ) { itkWarningMacro (<< "Unable to convert output number " << idx << " to type " << typeid( IGTLMessage ).name () ); } return out; } mitk::IGTLMessage* mitk::IGTLMessageSource::GetOutput( const std::string& messageName) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::iterator it = outputs.begin(); it != outputs.end(); ++it) { if (messageName == (static_cast(it->GetPointer()))->GetName()) { return static_cast(it->GetPointer()); } } return nullptr; } itk::ProcessObject::DataObjectPointerArraySizeType mitk::IGTLMessageSource::GetOutputIndex( std::string messageName ) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::size_type i = 0; i < outputs.size(); ++i) { if (messageName == (static_cast(outputs.at(i).GetPointer()))->GetName()) { return i; } } throw std::invalid_argument("output name does not exist"); } void mitk::IGTLMessageSource::RegisterAsMicroservice() { // Get Context us::ModuleContext* context = us::GetModuleContext(); // Define ServiceProps us::ServiceProperties props; mitk::UIDGenerator uidGen = mitk::UIDGenerator ("org.mitk.services.IGTLMessageSource.id_", 16); props[ US_PROPKEY_ID ] = uidGen.GetUID(); props[ US_PROPKEY_DEVICENAME ] = m_Name; props[ US_PROPKEY_DEVICETYPE ] = m_Type; m_ServiceRegistration = context->RegisterService(this, props); } void mitk::IGTLMessageSource::UnRegisterMicroservice() { if (m_ServiceRegistration != nullptr) - m_ServiceRegistration.Unregister(); + { + m_ServiceRegistration.Unregister(); + } m_ServiceRegistration = 0; } std::string mitk::IGTLMessageSource::GetMicroserviceID() { us::Any referenceProperty = this->m_ServiceRegistration.GetReference().GetProperty(US_PROPKEY_ID); return referenceProperty.ToString(); } void mitk::IGTLMessageSource::GraftOutput(itk::DataObject *graft) { this->GraftNthOutput(0, graft); } void mitk::IGTLMessageSource::GraftNthOutput(unsigned int idx, itk::DataObject *graft) { if ( idx >= this->GetNumberOfIndexedOutputs() ) { itkExceptionMacro(<<"Requested to graft output " << idx << " but this filter" "only has " << this->GetNumberOfIndexedOutputs() << " Outputs."); } if ( !graft ) { itkExceptionMacro(<<"Requested to graft output with a nullptr pointer object" ); } itk::DataObject* output = this->GetOutput(idx); if ( !output ) { itkExceptionMacro(<<"Requested to graft output that is a nullptr pointer" ); } // Call Graft on IGTLMessage to copy member data output->Graft( graft ); } itk::DataObject::Pointer mitk::IGTLMessageSource::MakeOutput ( DataObjectPointerArraySizeType /*idx*/ ) { return IGTLMessage::New().GetPointer(); } itk::DataObject::Pointer mitk::IGTLMessageSource::MakeOutput( const DataObjectIdentifierType & name ) { itkDebugMacro("MakeOutput(" << name << ")"); if( this->IsIndexedOutputName(name) ) { return this->MakeOutput( this->MakeIndexFromOutputName(name) ); } return static_cast(IGTLMessage::New().GetPointer()); } mitk::PropertyList::ConstPointer mitk::IGTLMessageSource::GetParameters() const { mitk::PropertyList::Pointer p = mitk::PropertyList::New(); // add properties to p like this: //p->SetProperty("MyFilter_MyParameter", mitk::PropertyDataType::New(m_MyParameter)); return mitk::PropertyList::ConstPointer(p); } void mitk::IGTLMessageSource::SetFPS(unsigned int fps) { this->m_StreamingFPSMutex->Lock(); this->m_StreamingFPS = fps; this->m_StreamingFPSMutex->Unlock(); } unsigned int mitk::IGTLMessageSource::GetFPS() { unsigned int fps = 0; this->m_StreamingFPSMutex->Lock(); fps = this->m_StreamingFPS; this->m_StreamingFPSMutex->Unlock(); return fps; } diff --git a/Modules/US/USModel/mitkUSDevice.cpp b/Modules/US/USModel/mitkUSDevice.cpp index 05ea8dcffc..40913afa64 100644 --- a/Modules/US/USModel/mitkUSDevice.cpp +++ b/Modules/US/USModel/mitkUSDevice.cpp @@ -1,712 +1,717 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkUSDevice.h" #include "mitkImageReadAccessor.h" // US Control Interfaces #include "mitkUSControlInterfaceProbes.h" #include "mitkUSControlInterfaceBMode.h" #include "mitkUSControlInterfaceDoppler.h" // Microservices #include #include #include #include mitk::USDevice::PropertyKeys mitk::USDevice::GetPropertyKeys() { static mitk::USDevice::PropertyKeys propertyKeys; return propertyKeys; } mitk::USDevice::USImageCropArea mitk::USDevice::GetCropArea() { MITK_INFO << "Return Crop Area L:" << m_CropArea.cropLeft << " R:" << m_CropArea.cropRight << " T:" << m_CropArea.cropTop << " B:" << m_CropArea.cropBottom; return m_CropArea; } +unsigned int mitk::USDevice::GetSizeOfImageVector() +{ + return m_ImageVector.size(); +} + mitk::USDevice::USDevice(std::string manufacturer, std::string model) : mitk::ImageSource(), m_FreezeBarrier(nullptr), m_FreezeMutex(), m_MultiThreader(itk::MultiThreader::New()), m_ImageMutex(itk::FastMutexLock::New()), m_ThreadID(-1), m_ImageVector(), m_Spacing(), m_IGTLServer(nullptr), m_IGTLMessageProvider(nullptr), m_ImageToIGTLMsgFilter(nullptr), m_IsFreezed(false), m_DeviceState(State_NoState), m_NumberOfOutputs(1), m_ServiceProperties(), m_ServiceRegistration(), m_Manufacturer(manufacturer), m_Name(model), m_Comment(), m_SpawnAcquireThread(true), m_UnregisteringStarted(false) { USImageCropArea empty; empty.cropBottom = 0; empty.cropTop = 0; empty.cropLeft = 0; empty.cropRight = 0; this->m_CropArea = empty; // set number of outputs this->SetNumberOfIndexedOutputs(m_NumberOfOutputs); // create a new output mitk::Image::Pointer newOutput = mitk::Image::New(); this->SetNthOutput(0, newOutput); } mitk::USDevice::USDevice(mitk::USImageMetadata::Pointer metadata) : mitk::ImageSource(), m_FreezeBarrier(nullptr), m_FreezeMutex(), m_MultiThreader(itk::MultiThreader::New()), m_ImageMutex(itk::FastMutexLock::New()), m_ThreadID(-1), m_ImageVector(), m_Spacing(), m_IGTLServer(nullptr), m_IGTLMessageProvider(nullptr), m_ImageToIGTLMsgFilter(nullptr), m_IsFreezed(false), m_DeviceState(State_NoState), m_NumberOfOutputs(1), m_ServiceProperties(), m_ServiceRegistration(), m_SpawnAcquireThread(true), m_UnregisteringStarted(false) { m_Manufacturer = metadata->GetDeviceManufacturer(); m_Name = metadata->GetDeviceModel(); m_Comment = metadata->GetDeviceComment(); USImageCropArea empty; empty.cropBottom = 0; empty.cropTop = 0; empty.cropLeft = 0; empty.cropRight = 0; this->m_CropArea = empty; // set number of outputs this->SetNumberOfIndexedOutputs(m_NumberOfOutputs); // create a new output mitk::Image::Pointer newOutput = mitk::Image::New(); this->SetNthOutput(0, newOutput); } mitk::USDevice::~USDevice() { if (m_ThreadID >= 0) { m_MultiThreader->TerminateThread(m_ThreadID); } // make sure that the us device is not registered at the micro service // anymore after it is destructed this->UnregisterOnService(); } mitk::USAbstractControlInterface::Pointer mitk::USDevice::GetControlInterfaceCustom() { MITK_INFO << "Custom control interface does not exist for this object."; return nullptr; } mitk::USControlInterfaceBMode::Pointer mitk::USDevice::GetControlInterfaceBMode() { MITK_INFO << "Control interface BMode does not exist for this object."; return nullptr; } mitk::USControlInterfaceProbes::Pointer mitk::USDevice::GetControlInterfaceProbes() { MITK_INFO << "Control interface Probes does not exist for this object."; return nullptr; } mitk::USControlInterfaceDoppler::Pointer mitk::USDevice::GetControlInterfaceDoppler() { MITK_INFO << "Control interface Doppler does not exist for this object."; return nullptr; } void mitk::USDevice::SetManufacturer(std::string manufacturer) { m_Manufacturer = manufacturer; if (m_DeviceState >= State_Initialized) { this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_MANUFACTURER, manufacturer); } } void mitk::USDevice::SetName(std::string name) { m_Name = name; if (m_DeviceState >= State_Initialized) { this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_NAME, name); } } void mitk::USDevice::SetComment(std::string comment) { m_Comment = comment; if (m_DeviceState >= State_Initialized) { this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_COMMENT, comment); } } us::ServiceProperties mitk::USDevice::ConstructServiceProperties() { mitk::USDevice::PropertyKeys propertyKeys = mitk::USDevice::GetPropertyKeys(); us::ServiceProperties props; props[propertyKeys.US_PROPKEY_ISCONNECTED] = this->GetIsConnected() ? "true" : "false"; props[propertyKeys.US_PROPKEY_ISACTIVE] = this->GetIsActive() ? "true" : "false"; props[propertyKeys.US_PROPKEY_LABEL] = this->GetServicePropertyLabel(); // get identifier of selected probe if there is one selected mitk::USControlInterfaceProbes::Pointer probesControls = this->GetControlInterfaceProbes(); if (probesControls.IsNotNull() && probesControls->GetIsActive()) { mitk::USProbe::Pointer probe = probesControls->GetSelectedProbe(); if (probe.IsNotNull()) { props[propertyKeys.US_PROPKEY_PROBES_SELECTED] = probe->GetName(); } } props[propertyKeys.US_PROPKEY_CLASS] = GetDeviceClass(); props[propertyKeys.US_PROPKEY_MANUFACTURER] = m_Manufacturer; props[propertyKeys.US_PROPKEY_NAME] = m_Name; props[propertyKeys.US_PROPKEY_COMMENT] = m_Comment; m_ServiceProperties = props; return props; } void mitk::USDevice::UnregisterOnService() { // unregister on micro service if (m_ServiceRegistration && !m_UnregisteringStarted) { // make sure that unregister is not started a second // time due to a callback during unregister for example m_UnregisteringStarted = true; m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } } bool mitk::USDevice::Initialize() { if (!this->OnInitialization()) { return false; } m_DeviceState = State_Initialized; // Get Context and Module us::ModuleContext* context = us::GetModuleContext(); us::ServiceProperties props = this->ConstructServiceProperties(); m_ServiceRegistration = context->RegisterService(this, props); return true; } bool mitk::USDevice::Connect() { MITK_DEBUG << "mitk::USDevice::Connect() called"; if (this->GetIsConnected()) { MITK_INFO("mitkUSDevice") << "Tried to connect an ultrasound device that " "was already connected. Ignoring call..."; return true; } if (!this->GetIsInitialized()) { MITK_ERROR("mitkUSDevice") << "Cannot connect device if it is not in initialized state."; return false; } // Prepare connection, fail if this fails. if (!this->OnConnection()) { return false; } // Update state m_DeviceState = State_Connected; this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISCONNECTED, true); return true; } void mitk::USDevice::ConnectAsynchron() { this->m_MultiThreader->SpawnThread(this->ConnectThread, this); } bool mitk::USDevice::Disconnect() { if (!GetIsConnected()) { MITK_WARN << "Tried to disconnect an ultrasound device that was not " "connected. Ignoring call..."; return false; } // Prepare connection, fail if this fails. if (!this->OnDisconnection()) return false; // Update state m_DeviceState = State_Initialized; this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISCONNECTED, false); return true; } bool mitk::USDevice::Activate() { if (!this->GetIsConnected()) { MITK_INFO("mitkUSDevice") << "Cannot activate device if it is not in connected state."; return true; } if (OnActivation()) { m_DeviceState = State_Activated; m_FreezeBarrier = itk::ConditionVariable::New(); // spawn thread for aquire images if us device is active if (m_SpawnAcquireThread) { this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); } this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISACTIVE, true); this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL, this->GetServicePropertyLabel()); // initialize the b mode control properties of the micro service mitk::USControlInterfaceBMode::Pointer bmodeControls = this->GetControlInterfaceBMode(); if (bmodeControls.IsNotNull()) { bmodeControls->Initialize(); } } this->ProvideViaOIGTL(); return m_DeviceState == State_Activated; } void mitk::USDevice::ProvideViaOIGTL() { // create a new OpenIGTLink Server if (m_IGTLServer.IsNull()) m_IGTLServer = mitk::IGTLServer::New(true); m_IGTLServer->SetName(this->GetName()); // create a new OpenIGTLink Device source if (m_IGTLMessageProvider.IsNull()) m_IGTLMessageProvider = mitk::IGTLMessageProvider::New(); // set the OpenIGTLink server as the source for the device source m_IGTLMessageProvider->SetIGTLDevice(m_IGTLServer); // register the provider so that it can be configured with the IGTL manager // plugin. This could be hardcoded but now I already have the fancy plugin. m_IGTLMessageProvider->RegisterAsMicroservice(); m_ImageToIGTLMsgFilter = mitk::ImageToIGTLMessageFilter::New(); m_ImageToIGTLMsgFilter->ConnectTo(this); // set the name of this filter to identify it easier m_ImageToIGTLMsgFilter->SetName(this->GetName()); // register this filter as micro service. The message provider looks for // provided IGTLMessageSources, once it found this microservice and someone // requested this data type then the provider will connect with this filter // automatically. m_ImageToIGTLMsgFilter->RegisterAsMicroservice(); } void mitk::USDevice::Deactivate() { if (!this->GetIsActive()) { MITK_WARN("mitkUSDevice") << "Cannot deactivate a device which is not activae."; return; } if (!OnDeactivation()) { return; } DisableOIGTL(); m_DeviceState = State_Connected; this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISACTIVE, false); this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL, this->GetServicePropertyLabel()); } void mitk::USDevice::DisableOIGTL() { // TODO: This seems not to be enough cleanup to catch all cases. For example, if the device is disconnected // from the OIGTL GUI, this won't get cleaned up correctly. m_IGTLServer->CloseConnection(); m_IGTLMessageProvider->UnRegisterMicroservice(); m_ImageToIGTLMsgFilter->UnRegisterMicroservice(); } void mitk::USDevice::SetIsFreezed(bool freeze) { if (!this->GetIsActive()) { MITK_WARN("mitkUSDevice") << "Cannot freeze or unfreeze if device is not active."; return; } this->OnFreeze(freeze); if (freeze) { m_IsFreezed = true; } else { m_IsFreezed = false; // wake up the image acquisition thread m_FreezeBarrier->Signal(); } } bool mitk::USDevice::GetIsFreezed() { /* if (!this->GetIsActive()) { MITK_WARN("mitkUSDevice")("mitkUSTelemedDevice") << "Cannot get freeze state if the hardware interface is not ready. " "Returning false..."; return false; }*/ return m_IsFreezed; } void mitk::USDevice::PushFilter(AbstractOpenCVImageFilter::Pointer filter) { mitk::USImageSource::Pointer imageSource = this->GetUSImageSource(); if (imageSource.IsNull()) { MITK_ERROR << "ImageSource must not be null when pushing a filter."; mitkThrow() << "ImageSource must not be null when pushing a filter."; } imageSource->PushFilter(filter); } void mitk::USDevice::PushFilterIfNotPushedBefore( AbstractOpenCVImageFilter::Pointer filter) { mitk::USImageSource::Pointer imageSource = this->GetUSImageSource(); if (imageSource.IsNull()) { MITK_ERROR << "ImageSource must not be null when pushing a filter."; mitkThrow() << "ImageSource must not be null when pushing a filter."; } if (!imageSource->GetIsFilterInThePipeline(filter)) { imageSource->PushFilter(filter); } } bool mitk::USDevice::RemoveFilter(AbstractOpenCVImageFilter::Pointer filter) { mitk::USImageSource::Pointer imageSource = this->GetUSImageSource(); if (imageSource.IsNull()) { MITK_ERROR << "ImageSource must not be null when pushing a filter."; mitkThrow() << "ImageSource must not be null when removing a filter."; } return imageSource->RemoveFilter(filter); } void mitk::USDevice::UpdateServiceProperty(std::string key, std::string value) { m_ServiceProperties[key] = value; m_ServiceRegistration.SetProperties(m_ServiceProperties); // send event to notify listeners about the changed property m_PropertyChangedMessage(key, value); } void mitk::USDevice::UpdateServiceProperty(std::string key, double value) { std::stringstream stream; stream << value; this->UpdateServiceProperty(key, stream.str()); } void mitk::USDevice::UpdateServiceProperty(std::string key, bool value) { this->UpdateServiceProperty( key, value ? std::string("true") : std::string("false")); } /** mitk::Image* mitk::USDevice::GetOutput() { if (this->GetNumberOfOutputs() < 1) return nullptr; return static_cast(this->ProcessObject::GetPrimaryOutput()); } mitk::Image* mitk::USDevice::GetOutput(unsigned int idx) { if (this->GetNumberOfOutputs() < 1) return nullptr; return static_cast(this->ProcessObject::GetOutput(idx)); } void mitk::USDevice::GraftOutput(itk::DataObject *graft) { this->GraftNthOutput(0, graft); } void mitk::USDevice::GraftNthOutput(unsigned int idx, itk::DataObject *graft) { if ( idx >= this->GetNumberOfOutputs() ) { itkExceptionMacro(<<"Requested to graft output " << idx << " but this filter only has " << this->GetNumberOfOutputs() << " Outputs."); } if ( !graft ) { itkExceptionMacro(<<"Requested to graft output with a nullptr pointer object" ); } itk::DataObject* output = this->GetOutput(idx); if ( !output ) { itkExceptionMacro(<<"Requested to graft output that is a nullptr pointer" ); } // Call Graft on USImage to copy member data output->Graft( graft ); } */ void mitk::USDevice::GrabImage() { std::vector image = this->GetUSImageSource()->GetNextImage(); m_ImageMutex->Lock(); this->SetImageVector(image); m_ImageMutex->Unlock(); } //########### GETTER & SETTER ##################// bool mitk::USDevice::GetIsInitialized() { return m_DeviceState == State_Initialized; } bool mitk::USDevice::GetIsActive() { return m_DeviceState == State_Activated; } bool mitk::USDevice::GetIsConnected() { return m_DeviceState == State_Connected; } std::string mitk::USDevice::GetDeviceManufacturer() { return m_Manufacturer; } std::string mitk::USDevice::GetDeviceModel() { return m_Name; } std::string mitk::USDevice::GetDeviceComment() { return m_Comment; } void mitk::USDevice::SetSpacing(double xSpacing, double ySpacing) { m_Spacing[0] = xSpacing; m_Spacing[1] = ySpacing; m_Spacing[2] = 1; if( m_ImageVector.size() > 0 ) { for( size_t index = 0; index < m_ImageVector.size(); ++index ) { auto& image = m_ImageVector[index]; if( image.IsNotNull() && image->IsInitialized() ) { image->GetGeometry()->SetSpacing(m_Spacing); } } this->Modified(); } MITK_INFO << "Spacing: " << m_Spacing; } void mitk::USDevice::GenerateData() { m_ImageMutex->Lock(); for (unsigned int i = 0; i < m_ImageVector.size() && i < this->GetNumberOfIndexedOutputs(); ++i) { auto& image = m_ImageVector[i]; if (image.IsNull() || !image->IsInitialized()) { // skip image } else { mitk::Image::Pointer output = this->GetOutput(i); if (!output->IsInitialized() || output->GetDimension(0) != image->GetDimension(0) || output->GetDimension(1) != image->GetDimension(1) || output->GetDimension(2) != image->GetDimension(2) || output->GetPixelType() != image->GetPixelType()) { output->Initialize(image->GetPixelType(), image->GetDimension(), image->GetDimensions()); } // copy contents of the given image into the member variable mitk::ImageReadAccessor inputReadAccessor(image); output->SetImportVolume(inputReadAccessor.GetData()); output->SetGeometry(image->GetGeometry()); } } m_ImageMutex->Unlock(); }; std::string mitk::USDevice::GetServicePropertyLabel() { std::string isActive; if (this->GetIsActive()) { isActive = " (Active)"; } else { isActive = " (Inactive)"; } // e.g.: Zonare MyLab5 (Active) return m_Manufacturer + " " + m_Name + isActive; } ITK_THREAD_RETURN_TYPE mitk::USDevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct* pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; mitk::USDevice* device = (mitk::USDevice*)pInfo->UserData; while (device->GetIsActive()) { // lock this thread when ultrasound device is freezed if (device->m_IsFreezed) { itk::SimpleMutexLock* mutex = &(device->m_FreezeMutex); mutex->Lock(); if (device->m_FreezeBarrier.IsNotNull()) { device->m_FreezeBarrier->Wait(mutex); } } device->GrabImage(); } return ITK_THREAD_RETURN_VALUE; } ITK_THREAD_RETURN_TYPE mitk::USDevice::ConnectThread(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct* pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; mitk::USDevice* device = (mitk::USDevice*)pInfo->UserData; device->Connect(); return ITK_THREAD_RETURN_VALUE; } void mitk::USDevice::ProbeChanged(std::string probename) { this->UpdateServiceProperty(mitk::USDevice::GetPropertyKeys().US_PROPKEY_PROBES_SELECTED, probename); } void mitk::USDevice::DepthChanged(double depth) { this->UpdateServiceProperty(mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH, depth); } diff --git a/Modules/US/USModel/mitkUSDevice.h b/Modules/US/USModel/mitkUSDevice.h index 095f3fbf1b..bf60d5fd7f 100644 --- a/Modules/US/USModel/mitkUSDevice.h +++ b/Modules/US/USModel/mitkUSDevice.h @@ -1,489 +1,534 @@ /*=================================================================== 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 MITKUSDevice_H_HEADER_INCLUDED_ #define MITKUSDevice_H_HEADER_INCLUDED_ // STL #include // MitkUS #include "mitkUSProbe.h" #include #include "mitkUSImageSource.h" // MitkIGTL #include "mitkIGTLMessageProvider.h" #include "mitkIGTLServer.h" #include "mitkIGTLDeviceSource.h" #include "mitkImageToIGTLMessageFilter.h" // MITK #include #include #include // ITK #include #include // Microservices #include #include #include // DEPRECATED #include "mitkUSImageMetadata.h" namespace itk { template class SmartPointer; } namespace mitk { class USAbstractControlInterface; class USControlInterfaceBMode; class USControlInterfaceProbes; class USControlInterfaceDoppler; /** * \brief A device holds information about it's model, make and the connected probes. It is the * common super class for all devices and acts as an image source for mitkUSImages. It is the base class * for all US Devices, and every new device should extend it. * * US Devices support output of calibrated images, i.e. images that include a specific geometry. * To achieve this, call SetCalibration, and make sure that the subclass also calls apply * transformation at some point (The USDevice does not automatically apply the transformation to the image) * * Note that USDevices will be removed from micro servive when their * destructor is called. Registering into micro service is done when * mitk::USDevice::Initialize() is called. * * \ingroup US */ class MITKUS_EXPORT USDevice : public mitk::ImageSource { public: enum DeviceStates { State_NoState, State_Initialized, State_Connected, State_Activated }; mitkClassMacro(USDevice, mitk::ImageSource); itkSetMacro(SpawnAcquireThread, bool); itkGetMacro(SpawnAcquireThread, bool); struct USImageCropArea { int cropLeft; int cropRight; int cropBottom; int cropTop; }; /** * \brief These constants are used in conjunction with Microservices. * The constants aren't defined as static member attributes to avoid the * "static initialization order fiasco", which would occur when objects of * this class are used in module activators (for restoring stored device, * for example). */ struct PropertyKeys { const std::string US_INTERFACE_NAME; // Common Interface name of all US Devices. Used to refer to this device via Microservices const std::string US_PROPKEY_MANUFACTURER; const std::string US_PROPKEY_NAME; const std::string US_PROPKEY_COMMENT; const std::string US_PROPKEY_LABEL; // Human readable text represntation of this device const std::string US_PROPKEY_ISCONNECTED; // Whether this device is connected or not. const std::string US_PROPKEY_ISACTIVE; // Whether this device is active or not. const std::string US_PROPKEY_CLASS; // Class Name of this Object const std::string US_PROPKEY_PROBES_SELECTED; const std::string US_PROPKEY_BMODE_FREQUENCY; const std::string US_PROPKEY_BMODE_POWER; const std::string US_PROPKEY_BMODE_DEPTH; const std::string US_PROPKEY_BMODE_GAIN; const std::string US_PROPKEY_BMODE_REJECTION; const std::string US_PROPKEY_BMODE_DYNAMIC_RANGE; PropertyKeys() : US_INTERFACE_NAME("org.mitk.services.UltrasoundDevice"), US_PROPKEY_MANUFACTURER(US_INTERFACE_NAME + ".manufacturer"), US_PROPKEY_NAME(US_INTERFACE_NAME + ".name"), US_PROPKEY_COMMENT(US_INTERFACE_NAME + ".comment"), US_PROPKEY_LABEL(US_INTERFACE_NAME + ".label"), US_PROPKEY_ISCONNECTED(US_INTERFACE_NAME + ".isConnected"), US_PROPKEY_ISACTIVE(US_INTERFACE_NAME + ".isActive"), US_PROPKEY_CLASS(US_INTERFACE_NAME + ".class"), US_PROPKEY_PROBES_SELECTED(US_INTERFACE_NAME + ".probes.selected"), US_PROPKEY_BMODE_FREQUENCY(US_INTERFACE_NAME + ".bmode.frequency"), US_PROPKEY_BMODE_POWER(US_INTERFACE_NAME + ".bmode.power"), US_PROPKEY_BMODE_DEPTH(US_INTERFACE_NAME + ".bmode.depth"), US_PROPKEY_BMODE_GAIN(US_INTERFACE_NAME + ".bmode.gain"), US_PROPKEY_BMODE_REJECTION(US_INTERFACE_NAME + ".bmode.rejection"), US_PROPKEY_BMODE_DYNAMIC_RANGE(US_INTERFACE_NAME + ".bmode.dynamicRange") {} }; /** * \brief Event for being notified about changes of the micro service properties. * This event can be used if no micro service context is available. */ mitkNewMessage2Macro(PropertyChanged, const std::string&, const std::string&) /** * \return keys for the microservice properties of ultrasound devices */ static mitk::USDevice::PropertyKeys GetPropertyKeys(); /** * \brief Default getter for the custom control interface. * Has to be implemented in a subclass if a custom control interface is * available. Default implementation returns null. * * \return null pointer */ virtual itk::SmartPointer GetControlInterfaceCustom(); /** * \brief Default getter for the b mode control interface. * Has to be implemented in a subclass if a b mode control interface is * available. Default implementation returns null. * * \return null pointer */ virtual itk::SmartPointer GetControlInterfaceBMode(); /** * \brief Default getter for the probes control interface. * Has to be implemented in a subclass if a probes control interface is * available. Default implementation returns null. * * \return null pointer */ virtual itk::SmartPointer GetControlInterfaceProbes(); /** * \brief Default getter for the doppler control interface. * Has to be implemented in a subclass if a doppler control interface is * available. Default implementation returns null. * * \return null pointer */ virtual itk::SmartPointer GetControlInterfaceDoppler(); /** * \brief Changes device state to mitk::USDevice::State_Initialized. * During initialization the virtual method * mitk::USDevice::OnInitialization will be called. If this method * returns false the initialization process will be canceled. Otherwise * the mitk::USDevice is registered in a micro service. */ bool Initialize(); /** * \brief Connects this device. A connected device is ready to deliver images (i.e. be Activated). A Connected Device can be active. A disconnected Device cannot be active. * Internally calls onConnect and then registers the device with the service. A device usually should * override the OnConnection() method, but never the Connect() method, since this will possibly exclude the device * from normal service management. The exact flow of events is: * 0. Check if the device is already connected. If yes, return true anyway, but don't do anything. * 1. Call OnConnection() Here, a device should establish it's connection with the hardware Afterwards, it should be ready to start transmitting images at any time. * 2. If OnConnection() returns true ("successful"), then the device is registered with the service. * 3. if not, it the method itself returns false or may throw an expection, depeneding on the device implementation. * */ bool Connect(); void ConnectAsynchron(); /** * \brief Works analogously to mitk::USDevice::Connect(). Don't override this Method, but onDisconnection instead. */ bool Disconnect(); /** * \brief Activates this device. * After the activation process, the device will start to produce images. * This Method will fail, if the device is not connected. */ bool Activate(); /** * \brief Deactivates this device. * After the deactivation process, the device will no longer produce * images, but still be connected. */ void Deactivate(); /** * \brief Can toggle if ultrasound image is currently updated or freezed. * * \param freeze true to stop updating the ultrasound image, false to start updating again */ virtual void SetIsFreezed(bool freeze); /** * \return true if device is currently freezed (no image update is done), false otherwise */ virtual bool GetIsFreezed(); void PushFilter(AbstractOpenCVImageFilter::Pointer filter); void PushFilterIfNotPushedBefore(AbstractOpenCVImageFilter::Pointer filter); bool RemoveFilter(AbstractOpenCVImageFilter::Pointer filter); /** * @brief To be called when the used probe changed. Will update the service properties * @param probename of the now used probe */ void ProbeChanged(std::string probename); /** * @brief To be called when the scanning depth of the probe changed. Will update the service properties * @param depth that is now used */ void DepthChanged(double depth); /** * \brief Given property is updated in the device micro service. * This method is mainly for being used by the control interface * superclasses. You do not need to call it by yoursefs in your * concrete control interface classes. */ void UpdateServiceProperty(std::string key, std::string value); void UpdateServiceProperty(std::string key, double value); void UpdateServiceProperty(std::string key, bool value); //########### GETTER & SETTER ##################// /** * \brief Returns the Class of the Device. This Method must be reimplemented by every Inheriting Class. */ virtual std::string GetDeviceClass() = 0; /** * \brief True, if the device object is created and initialized, false otherwise. */ bool GetIsInitialized(); /** * \brief True, if the device is currently generating image data, false otherwise. */ bool GetIsActive(); /** * \brief True, if the device is currently ready to start transmitting image data or is already * transmitting image data. A disconnected device cannot be activated. */ bool GetIsConnected(); /* @return Returns the area that will be cropped from the US image. Is disabled / [0,0,0,0] by default. */ mitk::USDevice::USImageCropArea GetCropArea(); /* @return Returns the size of the m_ImageVector of the ultrasound device.*/ unsigned int GetSizeOfImageVector(); /** @return Returns the current image source of this device. */ virtual USImageSource::Pointer GetUSImageSource() = 0; /** \brief Deprecated -> use GetManufacturer() instead */ DEPRECATED(std::string GetDeviceManufacturer()); /** \brief Deprecated -> use GetName() instead */ DEPRECATED(std::string GetDeviceModel()); /** \brief Deprecated -> use GetCommend() instead */ DEPRECATED(std::string GetDeviceComment()); itkGetMacro(Manufacturer, std::string); itkGetMacro(Name, std::string); itkGetMacro(Comment, std::string); void SetManufacturer(std::string manufacturer); void SetName(std::string name); void SetComment(std::string comment); itkGetMacro(DeviceState, DeviceStates) itkGetMacro(ServiceProperties, us::ServiceProperties) void GrabImage(); - virtual void SetSpacing(double xSpacing, double ySpacing); + /** + * \brief Returns all probes for this device or an empty vector it no probes were set + * Returns a std::vector of all probes that exist for this device if there were probes set while creating or modifying this USVideoDevice. + * Otherwise it returns an empty vector. Therefore always check if vector is filled, before using it! + */ + virtual std::vector GetAllProbes() = 0; + /** + * \brief Cleans the std::vector containing all configured probes. + */ + virtual void DeleteAllProbes() {}; + + /** + * \brief Return current active probe for this USDevice + * Returns a pointer to the probe that is currently in use. If there were probes set while creating or modifying this USDevice. + * Returns null otherwise + */ + virtual mitk::USProbe::Pointer GetCurrentProbe() = 0; + + /** + \brief adds a new probe to the device + */ + virtual void AddNewProbe(mitk::USProbe::Pointer /*probe*/) {}; + + /** + * \brief get the probe by its name + * Returns a pointer to the probe identified by the given name. If no probe of given name exists for this Device 0 is returned. + */ + virtual mitk::USProbe::Pointer GetProbeByName(std::string name) = 0; + + /** + * \brief Removes the Probe with the given name + */ + virtual void RemoveProbeByName(std::string /*name*/) {}; + + /** + * \brief Sets the first existing probe or the default probe of the ultrasound device + * as the current probe of it. + */ + virtual void SetDefaultProbeAsCurrentProbe() {}; + + /** + * \brief Sets the probe with the given name as current probe if the named probe exists. + */ + virtual void SetCurrentProbe(std::string /*probename*/) {}; + + virtual void SetSpacing(double xSpacing, double ySpacing); protected: // Threading-Related itk::ConditionVariable::Pointer m_FreezeBarrier; itk::SimpleMutexLock m_FreezeMutex; itk::MultiThreader::Pointer m_MultiThreader; ///< itk::MultiThreader used for thread handling itk::FastMutexLock::Pointer m_ImageMutex; ///< mutex for images provided by the image source int m_ThreadID; ///< ID of the started thread virtual void SetImageVector(std::vector vec) { if (this->m_ImageVector != vec) { this->m_ImageVector = vec; this->Modified(); } } static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); static ITK_THREAD_RETURN_TYPE ConnectThread(void* pInfoStruct); std::vector m_ImageVector; // Variables to determine if spacing was calibrated and needs to be applied to the incoming images mitk::Vector3D m_Spacing; /** * \brief Registers an OpenIGTLink device as a microservice so that we can send the images of * this device via the network. */ void ProvideViaOIGTL(); /** * \brief Deregisters the microservices for OpenIGTLink. */ void DisableOIGTL(); mitk::IGTLServer::Pointer m_IGTLServer; mitk::IGTLMessageProvider::Pointer m_IGTLMessageProvider; mitk::ImageToIGTLMessageFilter::Pointer m_ImageToIGTLMsgFilter; bool m_IsFreezed; DeviceStates m_DeviceState; /* @brief defines the area that should be cropped from the US image */ USImageCropArea m_CropArea; /** * \brief This Method constructs the service properties which can later be used to * register the object with the Microservices * Return service properties */ us::ServiceProperties ConstructServiceProperties(); /** * \brief Remove this device from the micro service. */ void UnregisterOnService(); /** * \brief Is called during the initialization process. * Override this method in a subclass to handle the actual initialization. * If it returns false, the initialization process will be canceled. * * \return true if successful and false if unsuccessful * \throw mitk::Exception implementation may throw an exception to clarify what went wrong */ virtual bool OnInitialization() = 0; /** * \brief Is called during the connection process. * Override this method in a subclass to handle the actual connection. * If it returns false, the connection process will be canceled. * * \return true if successful and false if unsuccessful * \throw mitk::Exception implementation may throw an exception to clarify what went wrong */ virtual bool OnConnection() = 0; /** * \brief Is called during the disconnection process. * Override this method in a subclass to handle the actual disconnection. * If it returns false, the disconnection process will be canceled. * * \return true if successful and false if unsuccessful * \throw mitk::Exception implementation may throw an exception to clarify what went wrong */ virtual bool OnDisconnection() = 0; /** * \brief Is called during the activation process. * After this method is finished, the device should be generating images. * If it returns false, the activation process will be canceled. * * \return true if successful and false if unsuccessful * \throw mitk::Exception implementation may throw an exception to clarify what went wrong */ virtual bool OnActivation() = 0; /** * \brief Is called during the deactivation process. * After a call to this method the device should still be connected, * but not producing images anymore. * * \return true if successful and false if unsuccessful * \throw mitk::Exception implementation may throw an exception to clarify what went wrong */ virtual bool OnDeactivation() = 0; /** * \brief Called when mitk::USDevice::SetIsFreezed() is called. * Subclasses can overwrite this method to do additional actions. Default * implementation does noting. */ virtual void OnFreeze(bool) { } /** * \brief Enforces minimal Metadata to be set. */ USDevice(std::string manufacturer, std::string model); /** * \brief Constructs a device with the given Metadata. Make sure the Metadata contains meaningful content! * \deprecated Use USDevice(std::string manufacturer, std::string model) instead. */ USDevice(mitk::USImageMetadata::Pointer metadata); ~USDevice() override; /** * \brief Grabs the next frame from the Video input. * This method is called internally, whenever Update() is invoked by an Output. */ void GenerateData() override; std::string GetServicePropertyLabel(); unsigned int m_NumberOfOutputs; /** * \brief Properties of the device's Microservice. */ us::ServiceProperties m_ServiceProperties; /** * \brief The device's ServiceRegistration object that allows to modify it's Microservice registraton details. */ us::ServiceRegistration m_ServiceRegistration; private: std::string m_Manufacturer; std::string m_Name; std::string m_Comment; bool m_SpawnAcquireThread; bool m_UnregisteringStarted; }; } // namespace mitk // This is the microservice declaration. Do not meddle! MITK_DECLARE_SERVICE_INTERFACE(mitk::USDevice, "org.mitk.services.UltrasoundDevice") #endif // MITKUSDevice_H_HEADER_INCLUDED_ diff --git a/Modules/US/USModel/mitkUSDeviceReaderWriterConstants.h b/Modules/US/USModel/mitkUSDeviceReaderWriterConstants.h index 5535469911..1f19b0af85 100644 --- a/Modules/US/USModel/mitkUSDeviceReaderWriterConstants.h +++ b/Modules/US/USModel/mitkUSDeviceReaderWriterConstants.h @@ -1,53 +1,56 @@ /*=================================================================== 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 mitkUSDeviceReaderWriterConstants_H_HEADER_INCLUDED_ #define mitkUSDeviceReaderWriterConstants_H_HEADER_INCLUDED_ const static char* TAG_ULTRASOUNDDEVICE = "ULTRASOUNDDEVICE"; const static char* TAG_GENERALSETTINGS = "GENERALSETTINGS"; const static char* TAG_PROBES = "PROBES"; const static char* TAG_PROBE = "PROBE"; const static char* TAG_DEPTHS = "DEPTHS"; const static char* TAG_DEPTH = "DEPTH"; const static char* TAG_SPACING = "SPACING"; const static char* TAG_CROPPING = "CROPPING"; const static char* ATTR_FILEVERS = "filevers"; const static char* ATTR_TYPE = "type"; +const static char* ATTR_HOST = "host"; +const static char* ATTR_PORT = "port"; +const static char* ATTR_SERVER = "server"; const static char* ATTR_NAME = "name"; const static char* ATTR_MANUFACTURER = "manufacturer"; const static char* ATTR_MODEL = "model"; const static char* ATTR_COMMENT = "comment"; const static char* ATTR_IMAGESTREAMS = "imagestreams"; const static char* ATTR_GREYSCALE = "greyscale"; const static char* ATTR_RESOLUTIONOVERRIDE = "resolutionOverride"; const static char* ATTR_RESOLUTIONWIDTH = "resolutionWidth"; const static char* ATTR_RESOLUTIONHEIGHT = "resolutionHeight"; const static char* ATTR_SOURCEID = "sourceID"; const static char* ATTR_FILEPATH = "filepath"; const static char* ATTR_OPENCVPORT = "opencvPort"; const static char* ATTR_DEPTH = "depth"; const static char* ATTR_X = "x"; const static char* ATTR_Y = "y"; const static char* ATTR_TOP = "top"; const static char* ATTR_BOTTOM = "bottom"; const static char* ATTR_LEFT = "left"; const static char* ATTR_RIGHT = "right"; #endif // mitkUSDeviceReaderWriterConstants_H_HEADER_INCLUDED_ diff --git a/Modules/US/USModel/mitkUSDeviceReaderXML.cpp b/Modules/US/USModel/mitkUSDeviceReaderXML.cpp index 7e7aed1530..2ff8a4c5c9 100644 --- a/Modules/US/USModel/mitkUSDeviceReaderXML.cpp +++ b/Modules/US/USModel/mitkUSDeviceReaderXML.cpp @@ -1,205 +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. ===================================================================*/ // MITK #include "mitkUSDeviceReaderWriterConstants.h" #include "mitkUSDeviceReaderXML.h" #include #include #include // Third Party #include #include #include mitk::USDeviceReaderXML::USDeviceReaderXML() : AbstractFileReader( mitk::IGTMimeTypes::USDEVICEINFORMATIONXML_MIMETYPE(), "MITK USDevice Reader (XML)"), m_Filename("") { RegisterService(); } mitk::USDeviceReaderXML::~USDeviceReaderXML() { } -mitk::USDeviceReaderXML::USVideoDeviceConfigData &mitk::USDeviceReaderXML::GetUSVideoDeviceConfigData() +mitk::USDeviceReaderXML::USDeviceConfigData &mitk::USDeviceReaderXML::GetUSDeviceConfigData() { return m_DeviceConfig; } mitk::USDeviceReaderXML::USDeviceReaderXML(const mitk::USDeviceReaderXML& other) : AbstractFileReader(other) { } mitk::USDeviceReaderXML* mitk::USDeviceReaderXML::Clone() const { return new USDeviceReaderXML(*this); } std::vector> mitk::USDeviceReaderXML::Read() { MITK_WARN << "This method is not implemented. \ Please use the method ReadUltrasoundDeviceConfiguration() instead."; std::vector result; return result; } bool mitk::USDeviceReaderXML::ReadUltrasoundDeviceConfiguration() { MITK_INFO << "Try to start reading xml device configuration..."; if (m_Filename == "") { MITK_WARN << "Cannot read file - empty filename!"; return false; } TiXmlDocument document(m_Filename); if (!document.LoadFile()) { MITK_ERROR << "Error when opening and reading file :" << m_Filename; return false; } TiXmlHandle documentHandle(&document); TiXmlElement* ultrasoundDeviceTag = documentHandle.FirstChildElement(TAG_ULTRASOUNDDEVICE).ToElement(); if (ultrasoundDeviceTag == nullptr) { MITK_ERROR << "Error parsing the file :" << m_Filename << std::endl << "Wrong xml format structure."; return false; } //Extract attribute information of the ULTRASOUNDDEVICE-Tag: this->ExtractAttributeInformationOfUltrasoundDeviceTag(ultrasoundDeviceTag); TiXmlElement* generalSettingsTag = documentHandle.FirstChildElement(TAG_ULTRASOUNDDEVICE).FirstChildElement(TAG_GENERALSETTINGS).ToElement(); if (generalSettingsTag == nullptr) { MITK_ERROR << "Error parsing the GENERALSETTINGS-Tag in the file :" << m_Filename; return false; } //Extract attribute information of the GENERALSETTINGS-Tag: this->ExtractAttributeInformationOfGeneralSettingsTag(generalSettingsTag); TiXmlElement* probesTag = documentHandle.FirstChildElement(TAG_ULTRASOUNDDEVICE).FirstChildElement(TAG_PROBES).ToElement(); if (probesTag == nullptr) { MITK_ERROR << "Error: PROBES-Tag was not found in the file :" << m_Filename << "Therefore, creating default probe."; //Create default ultrasound probe: mitk::USProbe::Pointer ultrasoundProbeDefault = mitk::USProbe::New(); ultrasoundProbeDefault->SetName("default"); ultrasoundProbeDefault->SetDepth(0); m_DeviceConfig.probes.push_back(ultrasoundProbeDefault); return true; } //Extract all saved and configured probes of the USDevice: for (TiXmlElement* probeTag = probesTag->FirstChildElement(TAG_PROBE); probeTag != nullptr; probeTag = probeTag->NextSiblingElement()) { this->ExtractProbe(probeTag); } return true; } void mitk::USDeviceReaderXML::SetFilename(std::string filename) { m_Filename = filename; } void mitk::USDeviceReaderXML::ExtractAttributeInformationOfUltrasoundDeviceTag(TiXmlElement *ultrasoundTag) { ultrasoundTag->QueryDoubleAttribute(ATTR_FILEVERS, &m_DeviceConfig.fileversion); ultrasoundTag->QueryStringAttribute(ATTR_TYPE, &m_DeviceConfig.deviceType); ultrasoundTag->QueryStringAttribute(ATTR_NAME, &m_DeviceConfig.deviceName); ultrasoundTag->QueryStringAttribute(ATTR_MANUFACTURER, &m_DeviceConfig.manufacturer); ultrasoundTag->QueryStringAttribute(ATTR_MODEL, &m_DeviceConfig.model); ultrasoundTag->QueryStringAttribute(ATTR_COMMENT, &m_DeviceConfig.comment); ultrasoundTag->QueryIntAttribute(ATTR_IMAGESTREAMS, &m_DeviceConfig.numberOfImageStreams); + ultrasoundTag->QueryStringAttribute(ATTR_HOST, &m_DeviceConfig.host); + ultrasoundTag->QueryIntAttribute(ATTR_PORT, &m_DeviceConfig.port); + ultrasoundTag->QueryBoolAttribute(ATTR_SERVER, &m_DeviceConfig.server); } void mitk::USDeviceReaderXML::ExtractAttributeInformationOfGeneralSettingsTag(TiXmlElement *generalSettingsTag) { generalSettingsTag->QueryBoolAttribute(ATTR_GREYSCALE, &m_DeviceConfig.useGreyscale); generalSettingsTag->QueryBoolAttribute(ATTR_RESOLUTIONOVERRIDE, &m_DeviceConfig.useResolutionOverride); generalSettingsTag->QueryIntAttribute(ATTR_RESOLUTIONHEIGHT, &m_DeviceConfig.resolutionHeight); generalSettingsTag->QueryIntAttribute(ATTR_RESOLUTIONWIDTH, &m_DeviceConfig.resolutionWidth); generalSettingsTag->QueryIntAttribute(ATTR_SOURCEID, &m_DeviceConfig.sourceID); generalSettingsTag->QueryStringAttribute(ATTR_FILEPATH, &m_DeviceConfig.filepathVideoSource); generalSettingsTag->QueryIntAttribute(ATTR_OPENCVPORT, &m_DeviceConfig.opencvPort); } void mitk::USDeviceReaderXML::ExtractProbe(TiXmlElement *probeTag) { mitk::USProbe::Pointer ultrasoundProbe = mitk::USProbe::New(); std::string probeName; probeTag->QueryStringAttribute(ATTR_NAME, &probeName); ultrasoundProbe->SetName(probeName); TiXmlElement* depthsTag = probeTag->FirstChildElement(TAG_DEPTHS); if (depthsTag != nullptr) { for (TiXmlElement* depthTag = depthsTag->FirstChildElement(TAG_DEPTH); depthTag != nullptr; depthTag = depthTag->NextSiblingElement()) { int depth = 0; mitk::Vector3D spacing; spacing[0] = 1; spacing[1] = 1; spacing[2] = 1; depthTag->QueryIntAttribute(ATTR_DEPTH, &depth); TiXmlElement* spacingTag = depthTag->FirstChildElement(TAG_SPACING); if (spacingTag != nullptr) { spacingTag->QueryDoubleAttribute(ATTR_X, &spacing[0]); spacingTag->QueryDoubleAttribute(ATTR_Y, &spacing[1]); } ultrasoundProbe->SetDepthAndSpacing(depth, spacing); } } else { MITK_ERROR << "Error: DEPTHS-Tag was not found in the file :" << m_Filename << "Therefore, creating default depth [0] and spacing [1,1,1] for the probe."; ultrasoundProbe->SetDepth(0); } unsigned int croppingTop = 0; unsigned int croppingBottom = 0; unsigned int croppingLeft = 0; unsigned int croppingRight = 0; TiXmlElement* croppingTag = probeTag->FirstChildElement(TAG_CROPPING); if (croppingTag != nullptr) { croppingTag->QueryUnsignedAttribute(ATTR_TOP, &croppingTop); croppingTag->QueryUnsignedAttribute(ATTR_BOTTOM, &croppingBottom); croppingTag->QueryUnsignedAttribute(ATTR_LEFT, &croppingLeft); croppingTag->QueryUnsignedAttribute(ATTR_RIGHT, &croppingRight); } ultrasoundProbe->SetProbeCropping(croppingTop, croppingBottom, croppingLeft, croppingRight); m_DeviceConfig.probes.push_back(ultrasoundProbe); } diff --git a/Modules/US/USModel/mitkUSDeviceReaderXML.h b/Modules/US/USModel/mitkUSDeviceReaderXML.h index 2b6c0a4fde..291d8dbb16 100644 --- a/Modules/US/USModel/mitkUSDeviceReaderXML.h +++ b/Modules/US/USModel/mitkUSDeviceReaderXML.h @@ -1,101 +1,105 @@ /*=================================================================== 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 mitkUSDeviceReaderXML_H_HEADER_INCLUDED_ #define mitkUSDeviceReaderXML_H_HEADER_INCLUDED_ #include #include #include class TiXmlElement; class TiXmlNode; namespace mitk { class MITKUS_EXPORT USDeviceReaderXML : public AbstractFileReader { public: USDeviceReaderXML(); ~USDeviceReaderXML() override; using AbstractFileReader::Read; std::vector> Read() override; bool ReadUltrasoundDeviceConfiguration(); void SetFilename(std::string filename); - typedef struct USVideoDeviceConfigData_ + typedef struct USDeviceConfigData_ { double fileversion; std::string deviceType; std::string deviceName; std::string manufacturer; std::string model; std::string comment; + std::string host; + int port; + bool server; int numberOfImageStreams; bool useGreyscale; bool useResolutionOverride; int resolutionWidth; int resolutionHeight; int sourceID; std::string filepathVideoSource; int opencvPort; std::vector probes; - USVideoDeviceConfigData_() + USDeviceConfigData_() : fileversion(0), deviceType("Unknown"), deviceName("Unknown"), - manufacturer("Unknown"), comment(""), numberOfImageStreams(1), + manufacturer("Unknown"), comment(""), host("localhost"), + port(18944), server(false), numberOfImageStreams(1), useGreyscale(true), useResolutionOverride(true), resolutionWidth(640), resolutionHeight(480), sourceID(0), filepathVideoSource(""), opencvPort(0) { }; - }USVideoDeviceConfigData; + }USDeviceConfigData; - USVideoDeviceConfigData &GetUSVideoDeviceConfigData(); + USDeviceConfigData &GetUSDeviceConfigData(); protected: USDeviceReaderXML(const USDeviceReaderXML& other); mitk::USDeviceReaderXML* Clone() const override; /** * \brief Extracts all stored attribute information of the ULTRASOUNDDEVICE-Tag. */ void ExtractAttributeInformationOfUltrasoundDeviceTag(TiXmlElement *element); /** * \brief Extracts all stored attribute information of the GENERALSETTINGS-Tag. */ void ExtractAttributeInformationOfGeneralSettingsTag(TiXmlElement *element); /** * \brief Extracts all stored information of a single ultrasound probe. */ void ExtractProbe(TiXmlElement *element); private: std::string m_Filename; - USVideoDeviceConfigData m_DeviceConfig; + USDeviceConfigData m_DeviceConfig; }; } // namespace mitk #endif // mitkUSDeviceReaderXML_H_HEADER_INCLUDED_ diff --git a/Modules/US/USModel/mitkUSDeviceWriterXML.cpp b/Modules/US/USModel/mitkUSDeviceWriterXML.cpp index 3a05ddb3d8..7e4272ffd3 100644 --- a/Modules/US/USModel/mitkUSDeviceWriterXML.cpp +++ b/Modules/US/USModel/mitkUSDeviceWriterXML.cpp @@ -1,157 +1,165 @@ /*=================================================================== 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. ===================================================================*/ // MITK #include "mitkUSDeviceReaderWriterConstants.h" #include "mitkUSDeviceWriterXML.h" #include #include #include // Third Party #include #include #include #include mitk::USDeviceWriterXML::USDeviceWriterXML() : AbstractFileWriter(USDevice::GetStaticNameOfClass(), mitk::IGTMimeTypes::USDEVICEINFORMATIONXML_MIMETYPE(), "MITK USDevice Writer (XML)"), m_Filename("") { RegisterService(); } mitk::USDeviceWriterXML::USDeviceWriterXML(const mitk::USDeviceWriterXML& other) : AbstractFileWriter(other) { } mitk::USDeviceWriterXML::~USDeviceWriterXML() { } mitk::USDeviceWriterXML* mitk::USDeviceWriterXML::Clone() const { return new USDeviceWriterXML(*this); } void mitk::USDeviceWriterXML::Write() { if (m_Filename == "") { MITK_WARN << "Cannot write to file - empty filename!"; return; } } void mitk::USDeviceWriterXML::SetFilename(std::string filename) { m_Filename = filename; } -bool mitk::USDeviceWriterXML::WriteUltrasoundVideoDeviceConfiguration(mitk::USDeviceReaderXML::USVideoDeviceConfigData & config) +bool mitk::USDeviceWriterXML::WriteUltrasoundDeviceConfiguration(mitk::USDeviceReaderXML::USDeviceConfigData & config) { TiXmlDocument document; TiXmlDeclaration* xmlDeclaration = new TiXmlDeclaration("1.0", "", ""); document.LinkEndChild(xmlDeclaration); //Create the xml information of the ULTRASOUNDDEVICE-Tag: TiXmlElement *ultrasoundDeviceTag = new TiXmlElement(TAG_ULTRASOUNDDEVICE); this->CreateXmlInformationOfUltrasoundDeviceTag(document, ultrasoundDeviceTag, config); //Create the xml information of the GENERALSETTINGS-Tag: TiXmlElement *generalSettingsTag = new TiXmlElement(TAG_GENERALSETTINGS); this->CreateXmlInformationOfGeneralSettingsTag(ultrasoundDeviceTag, generalSettingsTag, config); //Create the xml information of the PROBES-Tag: this->CreateXmlInformationOfProbesTag(ultrasoundDeviceTag, config); return document.SaveFile(m_Filename); } void mitk::USDeviceWriterXML::CreateXmlInformationOfUltrasoundDeviceTag( TiXmlDocument &document, TiXmlElement * ultrasoundDeviceTag, - mitk::USDeviceReaderXML::USVideoDeviceConfigData &config) + mitk::USDeviceReaderXML::USDeviceConfigData &config) { ultrasoundDeviceTag->SetAttribute(ATTR_FILEVERS, config.fileversion); ultrasoundDeviceTag->SetAttribute(ATTR_TYPE, config.deviceType); ultrasoundDeviceTag->SetAttribute(ATTR_NAME, config.deviceName); ultrasoundDeviceTag->SetAttribute(ATTR_MANUFACTURER, config.manufacturer); ultrasoundDeviceTag->SetAttribute(ATTR_MODEL, config.model); ultrasoundDeviceTag->SetAttribute(ATTR_COMMENT, config.comment); ultrasoundDeviceTag->SetAttribute(ATTR_IMAGESTREAMS, config.numberOfImageStreams); + if (config.deviceType.compare("oigtl") == 0) + { + ultrasoundDeviceTag->SetAttribute(ATTR_HOST, config.host); + ultrasoundDeviceTag->SetAttribute(ATTR_PORT, config.port); + std::string value = config.server ? "true" : "false"; + ultrasoundDeviceTag->SetAttribute(ATTR_SERVER, value); + } + document.LinkEndChild(ultrasoundDeviceTag); } -void mitk::USDeviceWriterXML::CreateXmlInformationOfGeneralSettingsTag(TiXmlElement *parentTag, TiXmlElement *generalSettingsTag, mitk::USDeviceReaderXML::USVideoDeviceConfigData & config) +void mitk::USDeviceWriterXML::CreateXmlInformationOfGeneralSettingsTag(TiXmlElement *parentTag, TiXmlElement *generalSettingsTag, mitk::USDeviceReaderXML::USDeviceConfigData & config) { std::string value = config.useGreyscale ? "true" : "false"; generalSettingsTag->SetAttribute(ATTR_GREYSCALE, value); value = config.useResolutionOverride ? "true" : "false"; generalSettingsTag->SetAttribute(ATTR_RESOLUTIONOVERRIDE, value); generalSettingsTag->SetAttribute(ATTR_RESOLUTIONWIDTH, config.resolutionWidth); generalSettingsTag->SetAttribute(ATTR_RESOLUTIONHEIGHT, config.resolutionHeight); generalSettingsTag->SetAttribute(ATTR_SOURCEID, config.sourceID); generalSettingsTag->SetAttribute(ATTR_FILEPATH, config.filepathVideoSource); generalSettingsTag->SetAttribute(ATTR_OPENCVPORT, config.opencvPort); parentTag->LinkEndChild(generalSettingsTag); } -void mitk::USDeviceWriterXML::CreateXmlInformationOfProbesTag(TiXmlElement * parentTag, mitk::USDeviceReaderXML::USVideoDeviceConfigData & config) +void mitk::USDeviceWriterXML::CreateXmlInformationOfProbesTag(TiXmlElement * parentTag, mitk::USDeviceReaderXML::USDeviceConfigData & config) { if (config.probes.size() != 0) { TiXmlElement *probesTag = new TiXmlElement(TAG_PROBES); parentTag->LinkEndChild(probesTag); for (size_t index = 0; index < config.probes.size(); ++index) { TiXmlElement *probeTag = new TiXmlElement(TAG_PROBE); probesTag->LinkEndChild(probeTag); mitk::USProbe::Pointer probe = config.probes.at(index); probeTag->SetAttribute(ATTR_NAME, probe->GetName()); std::map depthsAndSpacing = probe->GetDepthsAndSpacing(); if (depthsAndSpacing.size() != 0) { TiXmlElement *depthsTag = new TiXmlElement(TAG_DEPTHS); probeTag->LinkEndChild(depthsTag); for (std::map::iterator it = depthsAndSpacing.begin(); it != depthsAndSpacing.end(); it++) { TiXmlElement *depthTag = new TiXmlElement(TAG_DEPTH); depthTag->SetAttribute(ATTR_DEPTH, it->first); depthsTag->LinkEndChild(depthTag); TiXmlElement *spacingTag = new TiXmlElement(TAG_SPACING); spacingTag->SetDoubleAttribute(ATTR_X, it->second[0], 6); spacingTag->SetDoubleAttribute(ATTR_Y, it->second[1], 6); depthTag->LinkEndChild(spacingTag); } TiXmlElement *croppingTag = new TiXmlElement(TAG_CROPPING); probeTag->LinkEndChild(croppingTag); croppingTag->SetAttribute(ATTR_TOP, probe->GetProbeCropping().top); croppingTag->SetAttribute(ATTR_BOTTOM, probe->GetProbeCropping().bottom); croppingTag->SetAttribute(ATTR_LEFT, probe->GetProbeCropping().left); croppingTag->SetAttribute(ATTR_RIGHT, probe->GetProbeCropping().right); } } } } diff --git a/Modules/US/USModel/mitkUSDeviceWriterXML.h b/Modules/US/USModel/mitkUSDeviceWriterXML.h index 027733c578..24452a4c7e 100644 --- a/Modules/US/USModel/mitkUSDeviceWriterXML.h +++ b/Modules/US/USModel/mitkUSDeviceWriterXML.h @@ -1,92 +1,92 @@ /*=================================================================== 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 mitkUSDeviceWriterXML_H_Header_INCLUDED_ #define mitkUSDeviceWriterXML_H_Header_INCLUDED_ #include #include #include class TiXmlDocument; class TiXmlElement; namespace mitk { class MITKUS_EXPORT USDeviceWriterXML : public AbstractFileWriter { public: USDeviceWriterXML(); ~USDeviceWriterXML() override; using AbstractFileWriter::Write; void Write() override; /** * \brief Sets the filename of the ultrasound device configuration file which should be created. */ void SetFilename(std::string filename); /** * \brief Writes the configuration settings of an ultrasound device to a xml-file. * \param config The struct containing all information of the ultrasound device. */ - bool WriteUltrasoundVideoDeviceConfiguration(mitk::USDeviceReaderXML::USVideoDeviceConfigData &config); + bool WriteUltrasoundDeviceConfiguration(mitk::USDeviceReaderXML::USDeviceConfigData &config); protected: USDeviceWriterXML(const USDeviceWriterXML& other); mitk::USDeviceWriterXML* Clone() const override; /** * \brief Creates the xml ULTRASOUNDDEVICE-Tag entry of the ultrasound video device configuration file. * \param document A reference to the xml document. * \param ultrasoundDeviceTag The ULTRASOUNDDEVICETAG which should be created. * \param config The struct containing all information of the ultrasound device. */ void CreateXmlInformationOfUltrasoundDeviceTag( TiXmlDocument &document, TiXmlElement *ultrasoundDeviceTag, - mitk::USDeviceReaderXML::USVideoDeviceConfigData &config); + mitk::USDeviceReaderXML::USDeviceConfigData &config); /** * \brief Creates the xml GENERALSETTINGS-Tag entry of the ultrasound video device configuration file. * \param parentTag The xml parent tag of the GENERALSETTINGS-Tag. This is the ULTRASOUNDDEVICE-Tag. * \param generalSettingsTag The GENERALSETTINGS-Tag which should be created. * \param config The struct containing all information of the ultrasound device. */ void CreateXmlInformationOfGeneralSettingsTag( TiXmlElement *parentTag, TiXmlElement *generalSettingsTag, - mitk::USDeviceReaderXML::USVideoDeviceConfigData &config); + mitk::USDeviceReaderXML::USDeviceConfigData &config); /** * \brief Creates the xml PROBES-Tag entry of the ultrasound video device configuration file. All information * of all configured probes is extracted and then stored in the xml file. * \param parentTag The xml parent tag of the GENERALSETTINGS-Tag. This is the ULTRASOUNDDEVICE-Tag. * \param config The struct containing all information of the ultrasound device. */ void CreateXmlInformationOfProbesTag( TiXmlElement *parentTag, - mitk::USDeviceReaderXML::USVideoDeviceConfigData &config); + mitk::USDeviceReaderXML::USDeviceConfigData &config); private: /** * \brief The filename of the ultrasound device configuration file which should be created. */ std::string m_Filename; }; } #endif // mitkUSDeviceWriterXML_H_Header_INCLUDED_ diff --git a/Modules/US/USModel/mitkUSIGTLDevice.cpp b/Modules/US/USModel/mitkUSIGTLDevice.cpp index 17afb40fcd..5b8df067b3 100644 --- a/Modules/US/USModel/mitkUSIGTLDevice.cpp +++ b/Modules/US/USModel/mitkUSIGTLDevice.cpp @@ -1,72 +1,211 @@ /*=================================================================== 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 mitk::USIGTLDevice::USIGTLDevice(std::string manufacturer, std::string model, std::string host, int port, bool server) : mitk::USDevice(manufacturer, model), m_Host(host), m_Port(port) { + m_ControlInterfaceCustom = mitk::USVideoDeviceCustomControls::New(this); if (server) { m_Device = mitk::IGTLServer::New(true); } else { m_Device = mitk::IGTLClient::New(true); } m_Device->SetPortNumber(m_Port); m_Device->SetHostname(m_Host); m_Device->SetName(manufacturer + " - " + model); m_TransformDeviceSource = mitk::IGTLTrackingDataDeviceSource::New(); m_TransformDeviceSource->SetIGTLDevice(m_Device); m_TransformDeviceSource->RegisterAsMicroservice(); m_DeviceSource = mitk::IGTL2DImageDeviceSource::New(); m_DeviceSource->SetIGTLDevice(m_Device); m_DeviceSource->RegisterAsMicroservice(); m_Filter = mitk::IGTLMessageToUSImageFilter::New(); m_Filter->SetNumberOfExpectedOutputs(1); m_Filter->ConnectTo(m_DeviceSource); } std::string mitk::USIGTLDevice::GetDeviceClass() { return "IGTL Client"; } mitk::USImageSource::Pointer mitk::USIGTLDevice::GetUSImageSource() { return m_Filter.GetPointer(); } +mitk::USAbstractControlInterface::Pointer mitk::USIGTLDevice::GetControlInterfaceCustom() +{ + return m_ControlInterfaceCustom.GetPointer(); +} + +void mitk::USIGTLDevice::UnregisterOnService() +{ + m_DeviceSource->UnRegisterMicroservice(); + m_TransformDeviceSource->UnRegisterMicroservice(); + mitk::USDevice::UnregisterOnService(); +} + +std::vector mitk::USIGTLDevice::GetAllProbes() +{ + if (m_Probes.empty()) + { + MITK_INFO << "No probes exist for this USVideDevice. Empty vector is returned"; + } + return m_Probes; +} + +void mitk::USIGTLDevice::DeleteAllProbes() +{ + m_Probes.clear(); +} + +mitk::USProbe::Pointer mitk::USIGTLDevice::GetCurrentProbe() +{ + if (m_CurrentProbe.IsNotNull()) + { + return m_CurrentProbe; + } + else + { + return nullptr; + } +} + +void mitk::USIGTLDevice::AddNewProbe(mitk::USProbe::Pointer probe) +{ + m_Probes.push_back(probe); +} + +mitk::USProbe::Pointer mitk::USIGTLDevice::GetProbeByName(std::string name) +{ + for (std::vector::iterator it = m_Probes.begin(); it != m_Probes.end(); it++) + { + if (name.compare((*it)->GetName()) == 0) + return (*it); + } + MITK_INFO << "No probe with given name " << name << " was found."; + return nullptr; //no matching probe was found so 0 is returned +} + +void mitk::USIGTLDevice::RemoveProbeByName(std::string name) +{ + for (std::vector::iterator it = m_Probes.begin(); it != m_Probes.end(); it++) + { + if (name.compare((*it)->GetName()) == 0) + { + m_Probes.erase(it); + return; + } + } + MITK_INFO << "No Probe with given name " << name << " was found"; +} + +void mitk::USIGTLDevice::SetDefaultProbeAsCurrentProbe() +{ + if (m_Probes.size() == 0) + { + std::string name = "default"; + mitk::USProbe::Pointer defaultProbe = mitk::USProbe::New(name); + m_Probes.push_back(defaultProbe); + } + + m_CurrentProbe = m_Probes.at(0); + MITK_INFO << "SetDefaultProbeAsCurrentProbe()"; + this->ProbeChanged(m_CurrentProbe->GetName()); +} + +void mitk::USIGTLDevice::SetCurrentProbe(std::string probename) +{ + m_CurrentProbe = this->GetProbeByName(probename); + MITK_INFO << "SetCurrentProbe() " << probename; +} + +void mitk::USIGTLDevice::SetSpacing(double xSpacing, double ySpacing) +{ + mitk::Vector3D spacing; + spacing[0] = xSpacing; + spacing[1] = ySpacing; + spacing[2] = 1; + MITK_INFO << "Spacing: " << spacing; + + if (m_CurrentProbe.IsNotNull()) + { + m_CurrentProbe->SetSpacingForGivenDepth(m_CurrentProbe->GetCurrentDepth(), spacing); + } + else + { + MITK_WARN << "Cannot set spacing. Current ultrasound probe not set."; + } +} + bool mitk::USIGTLDevice::OnInitialization() { return true; } -bool mitk::USIGTLDevice::OnConnection() { return m_Device->OpenConnection(); } +bool mitk::USIGTLDevice::OnConnection() +{ + if (m_Device->GetState() == mitk::IGTLDevice::IGTLDeviceState::Running || + m_Device->GetState() == mitk::IGTLDevice::IGTLDeviceState::Ready) + { + MITK_INFO << "Device is ready or running. So return true"; + return true; + } + return m_Device->OpenConnection(); +} bool mitk::USIGTLDevice::OnDisconnection() { return m_Device->CloseConnection(); } bool mitk::USIGTLDevice::OnActivation() { + if (m_Device->GetState() == mitk::IGTLDevice::IGTLDeviceState::Running ) + { + MITK_INFO << "Device is running. So return true"; + return true; + } return m_Device->StartCommunication(); } bool mitk::USIGTLDevice::OnDeactivation() { return m_Device->StopCommunication(); } + +void mitk::USIGTLDevice::GenerateData() +{ + Superclass::GenerateData(); + if (m_ImageVector.size() == 0 || this->GetNumberOfIndexedOutputs() == 0) + { + return; + } + + m_ImageMutex->Lock(); + auto& image = m_ImageVector[0]; + if (image.IsNotNull() && image->IsInitialized() && m_CurrentProbe.IsNotNull()) + { + //MITK_INFO << "Spacing CurrentProbe: " << m_CurrentProbe->GetSpacingForGivenDepth(m_CurrentProbe->GetCurrentDepth()); + image->GetGeometry()->SetSpacing(m_CurrentProbe->GetSpacingForGivenDepth(m_CurrentProbe->GetCurrentDepth())); + this->GetOutput(0)->SetGeometry(image->GetGeometry()); + } + m_ImageMutex->Unlock(); +} diff --git a/Modules/US/USModel/mitkUSIGTLDevice.h b/Modules/US/USModel/mitkUSIGTLDevice.h index afa03c94f5..8e0291208b 100644 --- a/Modules/US/USModel/mitkUSIGTLDevice.h +++ b/Modules/US/USModel/mitkUSIGTLDevice.h @@ -1,69 +1,165 @@ /*=================================================================== 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 MITKIGTLDevice_H_HEADER_INCLUDED_ #define MITKIGTLDevice_H_HEADER_INCLUDED_ #include #include #include +#include #include #include #include #include #include +#include + + +namespace itk { + template class SmartPointer; +} namespace mitk { + class USVideoDeviceCustomControls; + class USAbstractControlInterface; /** * \brief A mitk::USIGTLDevice is a USDevice to receive images over an OpenIGTLink * connection. It registers an OIGTL device as a Microservice to receive image messages * and transforms them to mitk::Images. It can act both as a server (listening for * incoming connections) and as a client (connecting to an existing OIGTL server). * * \ingroup US */ class MITKUS_EXPORT USIGTLDevice : public mitk::USDevice { public: mitkClassMacro(USIGTLDevice, mitk::USDevice); // To open a device (Manufacturer, Model, Hostname, Port, IsServer) mitkNewMacro5Param(Self, std::string, std::string, std::string, int, bool); std::string GetDeviceClass() override; USImageSource::Pointer GetUSImageSource() override; USIGTLDevice(std::string manufacturer, std::string model, std::string host, int port, bool server); + /** + * Getter for the custom control interface which was created during the + * construction process of mitk::USIGTLDevice. + * + * \return custom control interface of the video device + */ + itk::SmartPointer GetControlInterfaceCustom() override; + + /** + * \brief Remove the IGTLDevice from the micro service. + */ + void UnregisterOnService(); + + // Neu hinzugefügt: + /** + * \brief Return all probes for this USVideoDevice or an empty vector it no probes were set + * Returns a std::vector of all probes that exist for this USVideoDevice if there were probes set while creating or modifying this USVideoDevice. + * Otherwise it returns an empty vector. Therefore always check if vector is filled, before using it! + */ + virtual std::vector GetAllProbes() override; + + /** + * \brief Cleans the std::vector containing all configured probes. + */ + virtual void DeleteAllProbes() override; + + /** + * \brief Return current active probe for this USDevice + * Returns a pointer to the probe that is currently in use. If there were probes set while creating or modifying this USDevice. + * Returns null otherwise + */ + virtual mitk::USProbe::Pointer GetCurrentProbe() override; + + /** + \brief adds a new probe to the device + */ + virtual void AddNewProbe(mitk::USProbe::Pointer probe) override; + + /** + * \brief get the probe by its name + * Returns a pointer to the probe identified by the given name. If no probe of given name exists for this Device 0 is returned. + */ + virtual mitk::USProbe::Pointer GetProbeByName(std::string name) override; + + /** + * \brief Removes the Probe with the given name + */ + virtual void RemoveProbeByName(std::string name) override; + + /** + * \brief Sets the first existing probe or the default probe of the video device + * as the current probe of it. + */ + virtual void SetDefaultProbeAsCurrentProbe() override; + + /** + * \brief Sets the probe with the given name as current probe if the named probe exists. + */ + virtual void SetCurrentProbe(std::string probename) override; + + /** + * \brief Sets the given spacing of the current depth of the current probe. + */ + void SetSpacing(double xSpacing, double ySpacing) override; + + protected: bool OnInitialization() override; bool OnConnection() override; bool OnDisconnection() override; bool OnActivation() override; bool OnDeactivation() override; + /** + * \brief Grabs the next frame from the Video input. + * This method is called internally, whenever Update() is invoked by an Output. + */ + virtual void GenerateData() override; + private: std::string m_Host; int m_Port; mitk::IGTLDevice::Pointer m_Device; mitk::IGTL2DImageDeviceSource::Pointer m_DeviceSource; mitk::IGTLTrackingDataDeviceSource::Pointer m_TransformDeviceSource; mitk::IGTLMessageToUSImageFilter::Pointer m_Filter; + + /** + * \brief custom control interface for us video device + */ + itk::SmartPointer m_ControlInterfaceCustom; + + /** + * \brief probes for this USVideoDevice + */ + std::vector < mitk::USProbe::Pointer > m_Probes; + + /** + \brief probe that is currently in use + */ + mitk::USProbe::Pointer m_CurrentProbe; }; } // namespace mitk #endif // MITKIGTLDevice_H_HEADER_INCLUDED_ diff --git a/Modules/US/USModel/mitkUSVideoDevice.h b/Modules/US/USModel/mitkUSVideoDevice.h index df205dd6c0..cb989d82ca 100644 --- a/Modules/US/USModel/mitkUSVideoDevice.h +++ b/Modules/US/USModel/mitkUSVideoDevice.h @@ -1,252 +1,252 @@ /*=================================================================== 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 MITKUSVideoDevice_H_HEADER_INCLUDED_ #define MITKUSVideoDevice_H_HEADER_INCLUDED_ #include #include #include "mitkUSDevice.h" #include "mitkUSImageVideoSource.h" #include "mitkUSProbe.h" #include namespace itk { template class SmartPointer; } namespace mitk { class USVideoDeviceCustomControls; class USAbstractControlInterface; /** * \brief A mitk::USVideoDevice is the common class for video only devices. * They capture video input either from a file or from a device and * transform the output into an mitk::USImage with attached metadata. * This simple implementation does only capture and display 2d images without * registration for example. * * \ingroup US */ class MITKUS_EXPORT USVideoDevice : public mitk::USDevice { public: mitkClassMacro(USVideoDevice, mitk::USDevice); // To open a device (DeviceID, Manufacturer, Model) mitkNewMacro3Param(Self, int, std::string, std::string); // To open A VideoFile (Path, Manufacturer, Model) mitkNewMacro3Param(Self, std::string, std::string, std::string); // To open a device (DeviceID, Metadata) mitkNewMacro2Param(Self, int, mitk::USImageMetadata::Pointer); // To open A VideoFile (Path, Metadata) mitkNewMacro2Param(Self, std::string, mitk::USImageMetadata::Pointer); /** * \return the qualified name of this class (as returned by GetDeviceClassStatic()) */ std::string GetDeviceClass() override; /** * This methode is necessary instead of a static member attribute to avoid * "static initialization order fiasco" when an instance of this class is * used in a module activator. * * \return the qualified name of this class */ static std::string GetDeviceClassStatic(); /** * Getter for the custom control interface which was created during the * construction process of mitk::USVideoDevice. * * \return custom control interface of the video device */ itk::SmartPointer GetControlInterfaceCustom() override; /** * \brief Remove this device from the micro service. * This method is public for mitk::USVideoDevice, 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(); /** * \return mitk::USImageSource connected to this device */ USImageSource::Pointer GetUSImageSource() override; /** * \brief Return all probes for this USVideoDevice or an empty vector it no probes were set * Returns a std::vector of all probes that exist for this USVideoDevice if there were probes set while creating or modifying this USVideoDevice. * Otherwise it returns an empty vector. Therefore always check if vector is filled, before using it! */ - std::vector GetAllProbes(); + virtual std::vector GetAllProbes() override; /** * \brief Cleans the std::vector containing all configured probes. */ - void DeleteAllProbes(); + virtual void DeleteAllProbes() override; /** * \brief Return current active probe for this USVideoDevice * Returns a pointer to the probe that is currently in use. If there were probes set while creating or modifying this USVideoDevice. * Returns null otherwise */ - mitk::USProbe::Pointer GetCurrentProbe(); + virtual mitk::USProbe::Pointer GetCurrentProbe() override; /** \brief adds a new probe to the device */ - void AddNewProbe(mitk::USProbe::Pointer probe); + virtual void AddNewProbe(mitk::USProbe::Pointer probe) override; /** * \brief get the probe by its name * Returns a pointer to the probe identified by the given name. If no probe of given name exists for this Device 0 is returned. */ - mitk::USProbe::Pointer GetProbeByName(std::string name); + virtual mitk::USProbe::Pointer GetProbeByName(std::string name) override; /** * \brief Removes the Probe with the given name */ - void RemoveProbeByName(std::string name); + virtual void RemoveProbeByName(std::string name) override; /** \brief True, if this Device plays back a file, false if it recieves data from a device */ bool GetIsSourceFile(); /** * \brief Sets the first existing probe or the default probe of the video device * as the current probe of it. */ - void SetDefaultProbeAsCurrentProbe(); + virtual void SetDefaultProbeAsCurrentProbe() override; /** * \brief Sets the probe with the given name as current probe if the named probe exists. */ - void SetCurrentProbe( std::string probename ); + virtual void SetCurrentProbe( std::string probename ) override; /** * \brief Sets the given spacing of the current depth of the current probe. */ void SetSpacing( double xSpacing, double ySpacing ) override; itkGetMacro(ImageVector, std::vector); itkGetMacro(DeviceID, int); itkGetMacro(FilePath, std::string); protected: /** * \brief Creates a new device that will deliver USImages taken from a video device. * under windows, try -1 for device number, which will grab the first available one * (Open CV functionality) */ USVideoDevice(int videoDeviceNumber, std::string manufacturer, std::string model); /** * \brief Creates a new device that will deliver USImages taken from a video file. */ USVideoDevice(std::string videoFilePath, std::string manufacturer, std::string model); /** * \brief Creates a new device that will deliver USImages taken from a video device. * under windows, try -1 for device number, which will grab the first available one * (Open CV functionality) */ USVideoDevice(int videoDeviceNumber, mitk::USImageMetadata::Pointer metadata); /** * \brief Creates a new device that will deliver USImages taken from a video file. */ USVideoDevice(std::string videoFilePath, mitk::USImageMetadata::Pointer metadata); ~USVideoDevice() override; /** * \brief Initializes common properties for all constructors. */ void Init(); /** * \brief Is called during the initialization process. * Returns true if successful and false if unsuccessful. Additionally, you may throw an exception to clarify what went wrong. */ bool OnInitialization() override; /** * \brief Is called during the connection process. * Returns true if successful and false if unsuccessful. Additionally, you may throw an exception to clarify what went wrong. */ bool OnConnection() override; /** * \brief Is called during the disconnection process. * Returns true if successful and false if unsuccessful. Additionally, you may throw an exception to clarify what went wrong. */ bool OnDisconnection() override; /** * \brief Is called during the activation process. After this method is finsihed, the device should be generating images */ bool OnActivation() override; /** * \brief Is called during the deactivation process. After a call to this method the device should still be connected, but not producing images anymore. */ bool OnDeactivation() override; /** * \brief Grabs the next frame from the Video input. * This method is called internally, whenever Update() is invoked by an Output. */ virtual void GenerateData() override; /** * \brief The image source that we use to aquire data */ mitk::USImageVideoSource::Pointer m_Source; /** * \brief True, if this source plays back a file, false if it recieves data from a device */ bool m_SourceIsFile; /** * \brief The device id to connect to. Undefined, if m_SourceIsFile == true; */ int m_DeviceID; /** * \brief The Filepath id to connect to. Undefined, if m_SourceIsFile == false; */ std::string m_FilePath; /** * \brief custom control interface for us video device */ itk::SmartPointer m_ControlInterfaceCustom; /** * \brief probes for this USVideoDevice */ std::vector < mitk::USProbe::Pointer > m_Probes; /** \brief probe that is currently in use */ mitk::USProbe::Pointer m_CurrentProbe; }; } // namespace mitk #endif // MITKUSVideoDevice_H_HEADER_INCLUDED_ diff --git a/Modules/US/USModel/mitkUSVideoDeviceCustomControls.cpp b/Modules/US/USModel/mitkUSVideoDeviceCustomControls.cpp index 72183efc48..7d187cf4f3 100644 --- a/Modules/US/USModel/mitkUSVideoDeviceCustomControls.cpp +++ b/Modules/US/USModel/mitkUSVideoDeviceCustomControls.cpp @@ -1,139 +1,134 @@ /*=================================================================== 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 "mitkUSVideoDeviceCustomControls.h" -mitk::USVideoDeviceCustomControls::USVideoDeviceCustomControls(itk::SmartPointer device) +mitk::USVideoDeviceCustomControls::USVideoDeviceCustomControls(itk::SmartPointer device) : mitk::USAbstractControlInterface(device.GetPointer()), m_IsActive(false) { m_ImageSource = dynamic_cast(m_Device->GetUSImageSource().GetPointer()); } mitk::USVideoDeviceCustomControls::~USVideoDeviceCustomControls() { } void mitk::USVideoDeviceCustomControls::SetIsActive(bool isActive) { m_IsActive = isActive; } bool mitk::USVideoDeviceCustomControls::GetIsActive() { return m_IsActive; } void mitk::USVideoDeviceCustomControls::SetCropArea(mitk::USImageVideoSource::USImageCropping newArea) { MITK_INFO << "Set Crop Area L:" << newArea.left << " R:" << newArea.right << " T:" << newArea.top << " B:" << newArea.bottom; if (m_ImageSource.IsNotNull()) { // if area is empty, remove region if ((newArea.bottom == 0) && (newArea.top == 0) && (newArea.left == 0) && (newArea.right == 0)) { m_ImageSource->RemoveRegionOfInterest(); } else { m_ImageSource->SetCropping(newArea); } } else { MITK_WARN << "Cannot set crop are, source is not initialized!"; } } void mitk::USVideoDeviceCustomControls::SetNewDepth(double depth) { - mitk::USVideoDevice::Pointer device = dynamic_cast(m_Device.GetPointer()); - if (device.IsNotNull()) + if (m_Device.IsNotNull()) { - if( device->GetCurrentProbe().IsNotNull() ) + if( m_Device->GetCurrentProbe().IsNotNull() ) { - device->GetCurrentProbe()->SetCurrentDepth(depth); + m_Device->GetCurrentProbe()->SetCurrentDepth(depth); MITK_INFO << "SetCurrentDepth of currentProbe: " << depth; } } m_Device->DepthChanged(depth); } void mitk::USVideoDeviceCustomControls::SetNewProbeIdentifier(std::string probename) { - mitk::USVideoDevice::Pointer device = dynamic_cast(m_Device.GetPointer()); - if( device.IsNotNull() ) + if( m_Device.IsNotNull() ) { - device->SetCurrentProbe(probename); + m_Device->SetCurrentProbe(probename); } m_Device->ProbeChanged(probename); } mitk::USProbe::USProbeCropping mitk::USVideoDeviceCustomControls::GetCropArea() { // just return the crop area set at the image source mitk::USVideoDevice::Pointer device = dynamic_cast(m_Device.GetPointer()); if (device.IsNotNull()) { mitk::USProbe::Pointer probe = device->GetCurrentProbe(); if (probe.IsNotNull()) { return probe->GetProbeCropping(); } } mitk::USProbe::USProbeCropping defaultCropping; return defaultCropping; } void mitk::USVideoDeviceCustomControls::UpdateProbeCropping(mitk::USImageVideoSource::USImageCropping cropping) { mitk::USVideoDevice::Pointer device = dynamic_cast(m_Device.GetPointer()); if (device.IsNotNull()) { mitk::USProbe::Pointer probe = device->GetCurrentProbe(); if( probe.IsNotNull() ) { probe->SetProbeCropping(cropping.top, cropping.bottom, cropping.left, cropping.right); } } } std::vector mitk::USVideoDeviceCustomControls::GetProbes() { - mitk::USVideoDevice::Pointer device = dynamic_cast(m_Device.GetPointer()); - return device->GetAllProbes(); + return m_Device->GetAllProbes(); } std::vector mitk::USVideoDeviceCustomControls::GetDepthsForProbe(std::string name) { - mitk::USVideoDevice::Pointer device = dynamic_cast(m_Device.GetPointer()); - mitk::USProbe::Pointer probe = device->GetProbeByName(name); + mitk::USProbe::Pointer probe = m_Device->GetProbeByName(name); std::map depthsAndSpacings = probe->GetDepthsAndSpacing(); std::vector depths; for (std::map::iterator it = depthsAndSpacings.begin(); it != depthsAndSpacings.end(); it++) { depths.push_back((it->first)); } return depths; } void mitk::USVideoDeviceCustomControls::SetDefaultProbeAsCurrentProbe() { - mitk::USVideoDevice::Pointer device = dynamic_cast(m_Device.GetPointer()); - device->SetDefaultProbeAsCurrentProbe(); + m_Device->SetDefaultProbeAsCurrentProbe(); } diff --git a/Modules/US/USModel/mitkUSVideoDeviceCustomControls.h b/Modules/US/USModel/mitkUSVideoDeviceCustomControls.h index 70b342011e..70ecdf4104 100644 --- a/Modules/US/USModel/mitkUSVideoDeviceCustomControls.h +++ b/Modules/US/USModel/mitkUSVideoDeviceCustomControls.h @@ -1,107 +1,107 @@ /*=================================================================== 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 MITKUSVideoDeviceCustomControls_H_HEADER_INCLUDED_ #define MITKUSVideoDeviceCustomControls_H_HEADER_INCLUDED_ #include "mitkUSAbstractControlInterface.h" #include "mitkUSImageVideoSource.h" #include "mitkUSVideoDevice.h" #include namespace mitk { /** * \brief Custom controls for mitk::USVideoDevice. * Controls image cropping of the corresponding mitk::USImageVideoSource. */ class MITKUS_EXPORT USVideoDeviceCustomControls : public USAbstractControlInterface { public: mitkClassMacro(USVideoDeviceCustomControls, USAbstractControlInterface); - mitkNewMacro1Param(Self, itk::SmartPointer); + mitkNewMacro1Param(Self, itk::SmartPointer); /** * Activate or deactivate the custom controls. This is just for handling * widget visibility in a GUI for example. Cropping will not be deactivated * if this method is called with false. Use * mitk::USVideoDeviceCustomControls::SetCropArea() with an empty are * instead. */ void SetIsActive(bool isActive) override; /** * \return if this custom controls are currently activated */ bool GetIsActive() override; /** * \brief Sets the area that will be cropped from the US image. * Set [0,0,0,0] to disable it, which is also default. */ void SetCropArea(USImageVideoSource::USImageCropping newArea); /** * \return area currently set for image cropping defined by the actual current probe. */ mitk::USProbe::USProbeCropping GetCropArea(); /** * \brief Updates the cropping of the current probe given by the crop area of the * USImageVideoSource. */ void UpdateProbeCropping( mitk::USImageVideoSource::USImageCropping cropping ); /** * \brief Sets a new depth value to the current probe. */ void SetNewDepth(double depth); /** * \ brief Sets new probe identifier */ void SetNewProbeIdentifier(std::string probename); /** *\brief Get all the probes for the current device */ std::vector GetProbes(); /** * \brief Get the scanning dephts of the given probe */ std::vector GetDepthsForProbe(std::string name); /** * \brief Sets the first existing probe or the default probe of a USVideoDevice * as the current probe of the USVideoDevice. */ void SetDefaultProbeAsCurrentProbe(); protected: /** * Class needs an mitk::USImageVideoSource object for beeing constructed. * This object will be manipulated by the custom controls methods. */ - USVideoDeviceCustomControls(itk::SmartPointer device); + USVideoDeviceCustomControls(itk::SmartPointer device); ~USVideoDeviceCustomControls() override; bool m_IsActive; USImageVideoSource::Pointer m_ImageSource; }; } // namespace mitk #endif // MITKUSVideoDeviceCustomControls_H_HEADER_INCLUDED_ \ No newline at end of file diff --git a/Modules/US/USNavigation/Testing/mitkCombinedModalityTest.cpp b/Modules/US/USNavigation/Testing/mitkCombinedModalityTest.cpp index 0556c322ba..f7dc20005a 100644 --- a/Modules/US/USNavigation/Testing/mitkCombinedModalityTest.cpp +++ b/Modules/US/USNavigation/Testing/mitkCombinedModalityTest.cpp @@ -1,180 +1,180 @@ /*=================================================================== 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 #include #include #include class mitkCombinedModalityTestClass { public: /* * \brief Returns a reference string for serialized calibrations. */ static std::string GetSerializedReference() { return std::string("\n<") + mitk::USCombinedModality::DefaultProbeIdentifier + mitk::USCombinedModality::ProbeAndDepthSeperator + "0 M00=\"1.1234\" M01=\"1.2234\" M02=\"1.3234\" M10=\"1.4234\" M11=\"1.5234\" M12=\"1.6234\" M20=\"1.7234\" M21=\"1.8234\" M22=\"1.9234\" T0=\"2.1234\" T1=\"2.2234\" T2=\"2.3234\" />\n\n"; } static bool CompareDoubles (double A, double B) { float diff = A - B; return (diff < 0.0001) && (-diff < 0.0001); } /* * \brief Creates a dummy combined modality. */ static mitk::USCombinedModality::Pointer CreateModality() { mitk::USVideoDevice::Pointer usDevice = mitk::USVideoDevice::New("IllegalPath", "Manufacturer", "Model"); mitk::VirtualTrackingDevice::Pointer tracker = mitk::VirtualTrackingDevice::New(); tracker->AddTool("tool1"); tracker->AddTool("tool2"); mitk::TrackingDeviceSource::Pointer source = mitk::TrackingDeviceSource::New(); source->SetTrackingDevice(tracker); source->Connect(); source->StartTracking(); - return mitk::USCombinedModality::New(usDevice.GetPointer(), source.GetPointer(), "MBI", "EchoTrack"); + return mitk::USCombinedModality::New(usDevice.GetPointer(), source.GetPointer(), false); } static void TestInstantiation() { mitk::USCombinedModality::Pointer combinedModality = CreateModality(); MITK_TEST_CONDITION_REQUIRED(combinedModality.IsNotNull(), "CombinedModality should not be null after instantiation"); } static void TestSerialization() { mitk::USCombinedModality::Pointer modality = CreateModality(); mitk::AffineTransform3D::MatrixType matrix; matrix[0][0] = 1.1234; matrix[0][1] = 1.2234; matrix[0][2] = 1.3234; matrix[1][0] = 1.4234; matrix[1][1] = 1.5234; matrix[1][2] = 1.6234; matrix[2][0] = 1.7234; matrix[2][1] = 1.8234; matrix[2][2] = 1.9234; mitk::AffineTransform3D::OffsetType offset; offset[0] = 2.1234; offset[1] = 2.2234; offset[2] = 2.3234; mitk::AffineTransform3D::Pointer transform = mitk::AffineTransform3D::New(); transform->SetMatrix(matrix); transform->SetOffset(offset); modality->SetCalibration(transform); MITK_TEST_CONDITION_REQUIRED(modality->SerializeCalibration() == GetSerializedReference(), "Testing correct Serialization..."); } static void TestDeserialization() { mitk::USCombinedModality::Pointer modality = CreateModality(); modality->DeserializeCalibration(GetSerializedReference()); mitk::AffineTransform3D::Pointer transform = modality->GetCalibration(); mitk::AffineTransform3D::MatrixType matrix = transform->GetMatrix(); mitk::AffineTransform3D::OffsetType offset = transform->GetOffset();; bool identical = true; if (! CompareDoubles(matrix[0][0], 1.1234)) identical = false; if (! CompareDoubles(matrix[0][1], 1.2234)) identical = false; if (! CompareDoubles(matrix[0][2], 1.3234)) identical = false; if (! CompareDoubles(matrix[1][0], 1.4234)) identical = false; if (! CompareDoubles(matrix[1][1], 1.5234)) identical = false; if (! CompareDoubles(matrix[1][2], 1.6234)) identical = false; if (! CompareDoubles(matrix[2][0], 1.7234)) identical = false; if (! CompareDoubles(matrix[2][1], 1.8234)) identical = false; if (! CompareDoubles(matrix[2][2], 1.9234)) identical = false; if (! CompareDoubles(offset[0], 2.1234)) identical = false; if (! CompareDoubles(offset[1], 2.2234)) identical = false; if (! CompareDoubles(offset[2], 2.3234)) identical = false; MITK_TEST_CONDITION_REQUIRED(identical, "Testing if deserialized calibration is identical to serialized one..."); // test if invalid strings cause exceptions MITK_TEST_FOR_EXCEPTION(mitk::Exception, modality->DeserializeCalibration("invalid-string")); MITK_TEST_FOR_EXCEPTION(mitk::Exception, modality->DeserializeCalibration("", false)); } static void TestFilterPipeline() { /*mitk::USCombinedModality::Pointer combinedModality = mitkCombinedModalityTestClass::CreateModality(); MITK_INFO << combinedModality->GetNavigationDataSource()->GetNameOfClass(); MITK_TEST_CONDITION(strcmp(combinedModality->GetNavigationDataSource()->GetNameOfClass(), "TrackingDeviceSource") == 0, "")*/ mitk::USVideoDevice::Pointer usDevice = mitk::USVideoDevice::New("IllegalPath", "Manufacturer", "Model"); mitk::VirtualTrackingDevice::Pointer tracker = mitk::VirtualTrackingDevice::New(); tracker->AddTool("tool1"); tracker->AddTool("tool2"); mitk::TrackingDeviceSource::Pointer source = mitk::TrackingDeviceSource::New(); source->SetTrackingDevice(tracker); source->Connect(); source->StartTracking(); - mitk::USCombinedModality::Pointer modality = mitk::USCombinedModality::New(usDevice.GetPointer(), source.GetPointer(), "MBI", "EchoTrack"); + mitk::USCombinedModality::Pointer modality = mitk::USCombinedModality::New(usDevice.GetPointer(), source.GetPointer(), false); MITK_TEST_CONDITION(source->GetOutput(0) == modality->GetNavigationDataSource()->GetOutput(0), "Navigation data output of the Combined Modality should be the same as the source output as no filters are active.") modality->SetNumberOfSmoothingValues(2); mitk::NavigationDataSource::Pointer smoothingFilter = modality->GetNavigationDataSource(); MITK_TEST_CONDITION(source->GetOutput(0) != smoothingFilter->GetOutput(0), "Navigation data output of the Combined Modality should be different to the source output as smoothing filter is active.") modality->SetNumberOfSmoothingValues(0); MITK_TEST_CONDITION(source->GetOutput(0) == modality->GetNavigationDataSource()->GetOutput(0), "Navigation data output of the Combined Modality should be the same as the source output again.") modality->SetDelayCount(5); MITK_TEST_CONDITION(source->GetOutput(0) != smoothingFilter->GetOutput(0), "Navigation data output of the Combined Modality should be different to the source output as delay filter is active.") modality->SetDelayCount(0); MITK_TEST_CONDITION(source->GetOutput(0) == modality->GetNavigationDataSource()->GetOutput(0), "Navigation data output of the Combined Modality should be the same as the source output again.") } }; /** * This function is testing methods of the class USDevice. */ int mitkCombinedModalityTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("mitkCombinedModalityTest"); mitkCombinedModalityTestClass::TestInstantiation(); mitkCombinedModalityTestClass::TestSerialization(); mitkCombinedModalityTestClass::TestDeserialization(); mitkCombinedModalityTestClass::TestFilterPipeline(); MITK_TEST_END(); } diff --git a/Modules/US/USNavigation/files.cmake b/Modules/US/USNavigation/files.cmake index b240daaede..0b77d91b58 100644 --- a/Modules/US/USNavigation/files.cmake +++ b/Modules/US/USNavigation/files.cmake @@ -1,5 +1,7 @@ SET(CPP_FILES mitkUSCombinedModality.cpp + mitkTrackedUltrasound.cpp + mitkAbstractUltrasoundTrackerDevice.cpp Filter/mitkNodeDisplacementFilter.cpp ) diff --git a/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.cpp b/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.cpp new file mode 100644 index 0000000000..bbb20fcd0e --- /dev/null +++ b/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.cpp @@ -0,0 +1,495 @@ +/*=================================================================== + +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 "mitkNavigationDataDelayFilter.h" +#include "mitkNavigationDataDisplacementFilter.h" +#include "mitkNavigationDataSmoothingFilter.h" +#include "mitkTrackingDeviceSource.h" + +// US Control Interfaces +#include "mitkUSControlInterfaceBMode.h" +#include "mitkUSControlInterfaceDoppler.h" +#include "mitkUSControlInterfaceProbes.h" + +// Microservices +#include +#include +#include +#include + +#include + +// TempIncludes +#include + +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.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_DisplacementFilter(mitk::NavigationDataDisplacementFilter::New()), + m_LastFilterOfIGTPipeline(nullptr), + m_NumberOfSmoothingValues(0), + m_DelayCount(0), + m_IsTrackedUltrasoundActive(trackedUltrasoundActive) +{ + m_DisplacementFilter->SetTransform6DOF(true); + + 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::AffineTransform3D::Pointer mitk::AbstractUltrasoundTrackerDevice::GetUSPlaneTransform() +{ + return mitk::AffineTransform3D::New(); +} + +void mitk::AbstractUltrasoundTrackerDevice::SetIsFreezed(bool freeze) +{ + if (m_UltrasoundDevice.IsNull() || m_TrackingDeviceDataSource.IsNull()) + { + MITK_WARN << "Combined modality not correctly initialized, aborting!"; + return; + } + + if (!m_UltrasoundDevice->GetIsActive()) + { + MITK_WARN("mitkUSDevice") + << "Cannot freeze or unfreeze if device is not active."; + return; + } + + this->OnFreeze(freeze); + + if (freeze) + { + m_IsFreezed = true; + } + else + { + m_IsFreezed = false; + } +} + +bool mitk::AbstractUltrasoundTrackerDevice::GetIsFreezed() +{ + return m_IsFreezed; +} + +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() +{ + if (m_LastFilterOfIGTPipeline.IsNull()) + { + this->RebuildFilterPipeline(); + } + m_LastFilterOfIGTPipeline->SetToolMetaDataCollection(this->m_TrackingDeviceDataSource->GetToolMetaDataCollection()); + return m_LastFilterOfIGTPipeline; +} + +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); +} + +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; +} + +void mitk::AbstractUltrasoundTrackerDevice::RebuildFilterPipeline() +{ + m_LastFilterOfIGTPipeline = m_TrackingDeviceDataSource; + + if (m_NumberOfSmoothingValues > 0) + { + m_SmoothingFilter->ConnectTo(m_LastFilterOfIGTPipeline.GetPointer()); + m_LastFilterOfIGTPipeline = m_SmoothingFilter; + } + + if (m_DelayCount > 0) + { + m_DelayFilter->ConnectTo(m_LastFilterOfIGTPipeline.GetPointer()); + m_LastFilterOfIGTPipeline = m_DelayFilter; + } + + if (m_IsTrackedUltrasoundActive) + { + m_DisplacementFilter->ConnectTo(m_LastFilterOfIGTPipeline.GetPointer()); + m_LastFilterOfIGTPipeline = m_DisplacementFilter; + } +} + +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.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::AbstractUltrasoundTrackerDevice::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::AbstractUltrasoundTrackerDevice::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::AbstractUltrasoundTrackerDevice::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::AbstractUltrasoundTrackerDevice::GetControlInterfaceDoppler() +{ + if (m_UltrasoundDevice.IsNull()) + { + MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; + mitkThrow() << "UltrasoundDevice must not be null."; + } + + return m_UltrasoundDevice->GetControlInterfaceDoppler(); +} diff --git a/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.h b/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.h new file mode 100644 index 0000000000..dfc8bb59a5 --- /dev/null +++ b/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.h @@ -0,0 +1,279 @@ +/*=================================================================== + +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; + class NavigationDataDisplacementFilter; + + /** + * \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); + + itkGetMacro(IsTrackedUltrasoundActive, bool); + + /** + * \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); + + /** Returns the index to world transform of the US plane. */ + virtual AffineTransform3D::Pointer GetUSPlaneTransform(); + + /** + * \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 Can toggle if the combined modality is currently updated or freezed. + * + * \param freeze true to stop updating the ultrasound image and the tracking data, false to start updating again + */ + virtual void SetIsFreezed(bool freeze); + + /** + * \return true if device is currently freezed (no image/tracking data update is done), false otherwise + */ + virtual bool GetIsFreezed(); + + /** + * \brief Called when mitk::AbstractUltrasoundTrackerDevice::SetIsFreezed() is called. + * Subclasses can overwrite this method to do additional actions. Default + * implementation does noting. + */ + virtual void OnFreeze(bool) { } + + protected: + AbstractUltrasoundTrackerDevice( USDevice::Pointer usDevice, + itk::SmartPointer trackingDevice, + bool trackedUltrasoundActive ); + virtual ~AbstractUltrasoundTrackerDevice(); + + + /** + * \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(); + + void RebuildFilterPipeline(); + + USDevice::Pointer m_UltrasoundDevice; + itk::SmartPointer m_TrackingDeviceDataSource; + std::map m_Calibrations; + + itk::SmartPointer m_SmoothingFilter; + itk::SmartPointer m_DelayFilter; + itk::SmartPointer m_DisplacementFilter; + itk::SmartPointer m_LastFilterOfIGTPipeline; + + 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_IsFreezed; + bool m_IsTrackedUltrasoundActive; + }; + +} // namespace mitk + +MITK_DECLARE_SERVICE_INTERFACE(mitk::AbstractUltrasoundTrackerDevice, "org.mitk.services.AbstractUltrasoundTrackerDevice") + +#endif diff --git a/Modules/US/USNavigation/mitkTrackedUltrasound.cpp b/Modules/US/USNavigation/mitkTrackedUltrasound.cpp new file mode 100644 index 0000000000..693bb0aa6b --- /dev/null +++ b/Modules/US/USNavigation/mitkTrackedUltrasound.cpp @@ -0,0 +1,105 @@ +/*=================================================================== + +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 "mitkTrackedUltrasound.h" +#include "mitkImageReadAccessor.h" +#include +#include +#include "mitkNavigationDataDisplacementFilter.h" +#include "mitkTrackingDeviceSource.h" + + + + +mitk::TrackedUltrasound::TrackedUltrasound( USDevice::Pointer usDevice, + NavigationDataSource::Pointer trackingDevice, + bool trackedUltrasoundActive ) + : AbstractUltrasoundTrackerDevice( usDevice, trackingDevice, trackedUltrasoundActive ) +{ +} + +mitk::TrackedUltrasound::~TrackedUltrasound() +{ +} + +mitk::AffineTransform3D::Pointer mitk::TrackedUltrasound::GetUSPlaneTransform() +{ + return m_UltrasoundDevice->GetOutput(0)->GetGeometry()->GetIndexToWorldTransform(); +} + +void mitk::TrackedUltrasound::GenerateData() +{ + //Call Update auf US-Device + evtl. auf Tracker (???) + + if (this->GetIsFreezed()) { return; } //if the image is freezed: do nothing + + //get next image from ultrasound image source + //FOR LATER: Be aware if the for loop behaves correct, if the UltrasoundDevice has more than 1 output. + int i = 0; + m_UltrasoundDevice->Update(); + mitk::Image::Pointer image = m_UltrasoundDevice->GetOutput(i); + if (image.IsNull() || !image->IsInitialized()) //check the image + { + MITK_WARN << "Invalid image in TrackedUltrasound, aborting!"; + return; + } + //___MITK_INFO << "GetSpacing: " << image->GetGeometry()->GetSpacing(); + + //get output and initialize it if it wasn't initialized before + mitk::Image::Pointer output = this->GetOutput(i); + 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 + m_DisplacementFilter->SetTransformation(calibrationIterator->second); + //Setze Update auf Displacementfilter ???? + } + } +} + +void mitk::TrackedUltrasound::OnFreeze(bool freeze) +{ + mitk::TrackingDeviceSource::Pointer trackingDeviceSource = dynamic_cast(m_TrackingDeviceDataSource.GetPointer()); + if (trackingDeviceSource.IsNull()) + { + MITK_WARN("TrackedUltrasound")("USDevice") << "Cannot freeze tracking."; + } + else + { + if (freeze) { trackingDeviceSource->Freeze(); } + else { trackingDeviceSource->UnFreeze(); } + } + + if (m_UltrasoundDevice.IsNull()) + { + MITK_ERROR("TrackedUltrasound")("USDevice") << "UltrasoundDevice must not be null."; + mitkThrow() << "UltrasoundDevice must not be null."; + } + m_UltrasoundDevice->SetIsFreezed(freeze); +} diff --git a/Modules/US/USNavigation/mitkTrackedUltrasound.h b/Modules/US/USNavigation/mitkTrackedUltrasound.h new file mode 100644 index 0000000000..32a3d81816 --- /dev/null +++ b/Modules/US/USNavigation/mitkTrackedUltrasound.h @@ -0,0 +1,72 @@ +/*=================================================================== + +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 __mitkTrackedUltrasound_h +#define __mitkTrackedUltrasound_h + +#include +#include "mitkUSDevice.h" +#include "mitkImageSource.h" +#include "mitkAbstractUltrasoundTrackerDevice.h" +#include "mitkNavigationDataSource.h" + +namespace itk { + template class SmartPointer; +} + +namespace mitk { + + /** + * \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 TrackedUltrasound : public mitk::AbstractUltrasoundTrackerDevice + { + public: + + mitkClassMacro(TrackedUltrasound, mitk::AbstractUltrasoundTrackerDevice); + mitkNewMacro3Param(TrackedUltrasound, USDevice::Pointer, itk::SmartPointer, bool); + virtual AffineTransform3D::Pointer GetUSPlaneTransform(); + + + + + protected: + TrackedUltrasound( USDevice::Pointer usDevice, + itk::SmartPointer trackingDevice, + bool trackedUltrasoundActive = true ); + virtual ~TrackedUltrasound(); + + /** + * \brief Grabs the next frame from the input. + * This method is called internally, whenever Update() is invoked by an Output. + */ + void GenerateData() override; + + /** + * \brief Freezes or unfreezes the TrackedUltrasound device. + */ + void OnFreeze(bool) override; + + }; +} // namespace mitk +#endif // __mitkTrackedUltrasound_h diff --git a/Modules/US/USNavigation/mitkUSCombinedModality.cpp b/Modules/US/USNavigation/mitkUSCombinedModality.cpp index 7c1baf9f71..b1ee4fcb5b 100644 --- a/Modules/US/USNavigation/mitkUSCombinedModality.cpp +++ b/Modules/US/USNavigation/mitkUSCombinedModality.cpp @@ -1,576 +1,104 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkUSCombinedModality.h" -#include "mitkUSDevice.h" -#include "mitkNavigationDataSource.h" #include "mitkImageReadAccessor.h" -#include -#include #include "mitkTrackingDeviceSource.h" +#include "mitkUSCombinedModality.h" +#include +#include // US Control Interfaces -#include "mitkUSControlInterfaceProbes.h" #include "mitkUSControlInterfaceBMode.h" #include "mitkUSControlInterfaceDoppler.h" +#include "mitkUSControlInterfaceProbes.h" -//Microservices -#include -#include -#include -#include - -#include - -//TempIncludes -#include - -const std::string mitk::USCombinedModality::DeviceClassIdentifier = "org.mitk.modules.us.USCombinedModality"; -const char* mitk::USCombinedModality::DefaultProbeIdentifier = "default"; -const char* mitk::USCombinedModality::ProbeAndDepthSeperator = "_"; - -const std::string mitk::USCombinedModality::US_INTERFACE_NAME = "org.mitk.services.USCombinedModality"; -const std::string mitk::USCombinedModality::US_PROPKEY_DEVICENAME = US_INTERFACE_NAME + ".devicename"; -const std::string mitk::USCombinedModality::US_PROPKEY_CLASS = US_INTERFACE_NAME + ".class"; -const std::string mitk::USCombinedModality::US_PROPKEY_ID = US_INTERFACE_NAME + ".id"; - -mitk::USCombinedModality::USCombinedModality(USDevice::Pointer usDevice, NavigationDataSource::Pointer trackingDevice, std::string manufacturer, std::string model) - : mitk::USDevice(manufacturer, model), m_UltrasoundDevice(usDevice), m_TrackingDevice(trackingDevice), - m_SmoothingFilter(mitk::NavigationDataSmoothingFilter::New()), m_DelayFilter(mitk::NavigationDataDelayFilter::New(0)), - m_NumberOfSmoothingValues(0), m_DelayCount(0) -{ - 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 - this->SetSpawnAcquireThread(false); -} - -mitk::USCombinedModality::~USCombinedModality() -{ -} - -std::string mitk::USCombinedModality::GetDeviceClass() -{ - return DeviceClassIdentifier; -} - -mitk::USImageSource::Pointer mitk::USCombinedModality::GetUSImageSource() -{ - if (m_UltrasoundDevice.IsNull()) - { - MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; - mitkThrow() << "UltrasoundDevice must not be null."; - } - - return m_UltrasoundDevice->GetUSImageSource(); -} - -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::UnregisterOnService() -{ - if (m_DeviceState == State_Activated) { this->Deactivate(); } - if (m_DeviceState == State_Connected) { this->Disconnect(); } - - mitk::USDevice::UnregisterOnService(); -} - -mitk::AffineTransform3D::Pointer mitk::USCombinedModality::GetCalibration() +mitk::USCombinedModality::USCombinedModality(USDevice::Pointer usDevice, + NavigationDataSource::Pointer trackingDevice, + bool trackedUltrasoundActive) + : AbstractUltrasoundTrackerDevice(usDevice, trackingDevice, trackedUltrasoundActive) { - return this->GetCalibration(this->GetCurrentDepthValue(), this->GetIdentifierForCurrentProbe()); } - -mitk::AffineTransform3D::Pointer mitk::USCombinedModality::GetCalibration(std::string depth) +mitk::AffineTransform3D::Pointer mitk::USCombinedModality::GetUSPlaneTransform() { - return this->GetCalibration(depth, this->GetIdentifierForCurrentProbe()); + return this->GetCalibration(); } -mitk::AffineTransform3D::Pointer mitk::USCombinedModality::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::USCombinedModality::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 nullptr; } - - return calibrationIterator->second; -} +mitk::USCombinedModality::~USCombinedModality() {} -void mitk::USCombinedModality::SetCalibration(mitk::AffineTransform3D::Pointer calibration) +void mitk::USCombinedModality::GenerateData() { - if (calibration.IsNull()) + if (this->GetIsFreezed()) { - 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::USCombinedModality::RemoveCalibration() -{ - return this->RemoveCalibration(this->GetCurrentDepthValue(), this->GetIdentifierForCurrentProbe()); -} - -bool mitk::USCombinedModality::RemoveCalibration(std::string depth) -{ - return this->RemoveCalibration(depth, this->GetIdentifierForCurrentProbe()); -} - -bool mitk::USCombinedModality::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::USCombinedModality::ProbeAndDepthSeperator + depth; - - return m_Calibrations.erase(calibrationKey) > 0; -} - -void mitk::USCombinedModality::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::USCombinedModality::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); -} - -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."; - } + } // if the image is freezed: do nothing - 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); -} - -mitk::NavigationDataSource::Pointer mitk::USCombinedModality::GetNavigationDataSource() -{ - return m_LastFilter.GetPointer(); -} - -bool mitk::USCombinedModality::GetIsCalibratedForCurrentStatus() -{ - return m_Calibrations.find(this->GetIdentifierForCurrentCalibration()) != m_Calibrations.end(); -} - -bool mitk::USCombinedModality::GetContainsAtLeastOneCalibration() -{ - return !m_Calibrations.empty(); -} - -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()[0]; - - if (image.IsNull() || !image->IsInitialized()) //check the image + // get next image from ultrasound image source + // FOR LATER: Be aware if the for loop behaves correct, if the UltrasoundDevice has more than 1 output. + m_UltrasoundDevice->Update(); + mitk::Image::Pointer image = m_UltrasoundDevice->GetOutput(0); + 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 + // get output and initialize it if it wasn't initialized before mitk::Image::Pointer output = this->GetOutput(); - if (!output->IsInitialized()) { output->Initialize(image); } + if (!output->IsInitialized()) + { + output->Initialize(image); + } - //now update image data + // 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 + 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) + // and update calibration (= transformation of the image) std::string calibrationKey = this->GetIdentifierForCurrentCalibration(); if (!calibrationKey.empty()) { - std::map::iterator calibrationIterator - = m_Calibrations.find(calibrationKey); + 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); } } } -std::string mitk::USCombinedModality::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::USCombinedModality::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; - } -} - -std::string mitk::USCombinedModality::GetIdentifierForCurrentCalibration() -{ - return this->GetIdentifierForCurrentProbe() - + mitk::USCombinedModality::ProbeAndDepthSeperator - + this->GetCurrentDepthValue(); -} - -std::string mitk::USCombinedModality::GetIdentifierForCurrentProbe() -{ - us::ServiceProperties usdeviceProperties = m_UltrasoundDevice->GetServiceProperties(); - - us::ServiceProperties::const_iterator probeIt = usdeviceProperties.find( - mitk::USCombinedModality::GetPropertyKeys().US_PROPKEY_PROBES_SELECTED); - - // get probe identifier from control interface for probes - std::string probeName = mitk::USCombinedModality::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::USCombinedModality::GetCurrentDepthValue() +void mitk::USCombinedModality::OnFreeze(bool freeze) { - 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::USCombinedModality::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH); - - if (depthIterator != usdeviceProperties.end()) + mitk::TrackingDeviceSource::Pointer trackingDeviceSource = dynamic_cast(m_TrackingDeviceDataSource.GetPointer()); + if (trackingDeviceSource.IsNull()) { - depth = depthIterator->second.ToString(); + MITK_WARN("USCombinedModality")("USDevice") << "Cannot freeze tracking."; } else { - depth = "0"; - } - - return depth; -} - -void mitk::USCombinedModality::RebuildFilterPipeline() -{ - m_LastFilter = m_TrackingDevice; - - if (m_NumberOfSmoothingValues > 0) - { - for (unsigned int i = 0; i < m_TrackingDevice->GetNumberOfOutputs(); i++) - { - m_SmoothingFilter->SetInput(i, m_LastFilter->GetOutput(i)); - } - m_LastFilter = m_SmoothingFilter; + if (freeze) { trackingDeviceSource->Freeze(); } + else { trackingDeviceSource->UnFreeze(); } } - if (m_DelayCount > 0) + if (m_UltrasoundDevice.IsNull()) { - for (unsigned int i = 0; i < m_TrackingDevice->GetNumberOfOutputs(); i++) - { - m_DelayFilter->SetInput(i, m_LastFilter->GetOutput(i)); - } - m_LastFilter = m_DelayFilter; + MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; + mitkThrow() << "UltrasoundDevice must not be null."; } -} - -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); - props[US_PROPKEY_ID] = uidGen.GetUID(); - props[US_PROPKEY_DEVICENAME] = this->GetName(); - props[US_PROPKEY_CLASS] = this->GetDeviceClass(); - - m_ServiceProperties = props; - - m_ServiceRegistration = context->RegisterService(this, props); + m_UltrasoundDevice->SetIsFreezed(freeze); } diff --git a/Modules/US/USNavigation/mitkUSCombinedModality.h b/Modules/US/USNavigation/mitkUSCombinedModality.h index a549299f54..6d8bf2781c 100644 --- a/Modules/US/USNavigation/mitkUSCombinedModality.h +++ b/Modules/US/USNavigation/mitkUSCombinedModality.h @@ -1,256 +1,77 @@ /*=================================================================== 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 NavigationDataSmoothingFilter; - class NavigationDataDelayFilter; class USControlInterfaceBMode; class USControlInterfaceProbes; class USControlInterfaceDoppler; /** * \brief Combination of USDevice and NavigationDataSource. - * This class can be used as any USDevice subclass. Additionally tracking data be + * 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 USDevice + class MITKUSNAVIGATION_EXPORT USCombinedModality : public mitk::AbstractUltrasoundTrackerDevice { public: - static const std::string DeviceClassIdentifier; - static const char* DefaultProbeIdentifier; - static const char* ProbeAndDepthSeperator; - - mitkClassMacro(USCombinedModality, USDevice); - mitkNewMacro4Param(USCombinedModality, USDevice::Pointer, itk::SmartPointer, std::string, std::string); - - itkGetMacro(UltrasoundDevice, itk::SmartPointer); - itkSetMacro(UltrasoundDevice, itk::SmartPointer); - itkGetMacro(TrackingDevice, itk::SmartPointer); - itkSetMacro(TrackingDevice, 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() override; - - /** - * \brief Wrapper for returning USImageSource of the UltrasoundDevice. - */ - USImageSource::Pointer GetUSImageSource() override; - - /** - * \brief Wrapper for returning custom control interface of the UltrasoundDevice. - */ - itk::SmartPointer GetControlInterfaceCustom() override; - - /** - * \brief Wrapper for returning B mode control interface of the UltrasoundDevice. - */ - itk::SmartPointer GetControlInterfaceBMode() override; - - /** - * \brief Wrapper for returning probes control interface of the UltrasoundDevice. - */ - itk::SmartPointer GetControlInterfaceProbes() override; - - /** - * \brief Wrapper for returning doppler control interface of the UltrasoundDevice. - */ - itk::SmartPointer GetControlInterfaceDoppler() override; - - virtual 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(); + mitkClassMacro(USCombinedModality, mitk::AbstractUltrasoundTrackerDevice); + mitkNewMacro3Param(USCombinedModality, USDevice::Pointer, itk::SmartPointer, bool); + virtual AffineTransform3D::Pointer GetUSPlaneTransform(); - /** - * \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(); - - /** - * \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); - - void RegisterAsMicroservice(); - - /** - *\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: - USCombinedModality(USDevice::Pointer usDevice, itk::SmartPointer trackingDevice, std::string manufacturer = "", std::string model = ""); - ~USCombinedModality() override; - - /** - * \brief Initializes UltrasoundDevice. - */ - bool OnInitialization() override; - - /** - * \brief Connects UltrasoundDevice. - */ - bool OnConnection() override; - - /** - * \brief Disconnects UltrasoundDevice. - */ - bool OnDisconnection() override; - - /** - * \brief Activates UltrasoundDevice. - */ - bool OnActivation() override; - - /** - * \brief Deactivates UltrasoundDevice. - */ - bool OnDeactivation() override; - - /** - * \brief Freezes or unfreezes UltrasoundDevice. - */ - void OnFreeze(bool) override; + USCombinedModality( USDevice::Pointer usDevice, + itk::SmartPointer trackingDevice, + bool trackedUltrasoundActive = false ); + virtual ~USCombinedModality(); /** * \brief Grabs the next frame from the input. * This method is called internally, whenever Update() is invoked by an Output. */ void GenerateData() override; - std::string GetIdentifierForCurrentCalibration(); - std::string GetIdentifierForCurrentProbe(); - std::string GetCurrentDepthValue(); - - void RebuildFilterPipeline(); - - USDevice::Pointer m_UltrasoundDevice; - itk::SmartPointer m_TrackingDevice; - std::map m_Calibrations; - - itk::SmartPointer m_SmoothingFilter; - itk::SmartPointer m_DelayFilter; - itk::SmartPointer m_LastFilter; - - unsigned int m_NumberOfSmoothingValues; - unsigned int m_DelayCount; + /** + * \brief Freezes or unfreezes the CombinedModality. + */ + void OnFreeze(bool) override; }; } // namespace mitk -//MITK_DECLARE_SERVICE_INTERFACE(mitk::USCombinedModality, "org.mitk.services.USCombinedModality") #endif // MITKUSCombinedModality_H_HEADER_INCLUDED_ diff --git a/Modules/USUI/Qmitk/QmitkUSDeviceManagerWidget.cpp b/Modules/USUI/Qmitk/QmitkUSDeviceManagerWidget.cpp index b1619bc1b6..e435fd1022 100644 --- a/Modules/USUI/Qmitk/QmitkUSDeviceManagerWidget.cpp +++ b/Modules/USUI/Qmitk/QmitkUSDeviceManagerWidget.cpp @@ -1,237 +1,253 @@ /*=================================================================== 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. ===================================================================*/ //#define _USE_MATH_DEFINES #include #include #include #include #include "mitkUSVideoDevice.h" +#include const std::string QmitkUSDeviceManagerWidget::VIEW_ID = "org.mitk.views.QmitkUSDeviceManagerWidget"; QmitkUSDeviceManagerWidget::QmitkUSDeviceManagerWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = nullptr; CreateQtPartControl(this); } QmitkUSDeviceManagerWidget::~QmitkUSDeviceManagerWidget() {} //////////////////// INITIALIZATION ///////////////////// void QmitkUSDeviceManagerWidget::CreateQtPartControl(QWidget* parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkUSDeviceManagerWidgetControls; m_Controls->setupUi(parent); this->CreateConnections(); m_Controls->m_ConnectedDevices->SetAutomaticallySelectFirstEntry(true); } // Initializations std::string empty = ""; m_Controls->m_ConnectedDevices->Initialize( mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL, empty); } void QmitkUSDeviceManagerWidget::CreateConnections() { if (m_Controls) { connect(m_Controls->m_BtnActivate, SIGNAL(clicked()), this, SLOT(OnClickedActivateDevice())); // connect( m_Controls->m_BtnDisconnect, SIGNAL( clicked() ), this, // SLOT(OnClickedDisconnectDevice()) ); connect(m_Controls->m_BtnRemove, SIGNAL(clicked()), this, SLOT(OnClickedRemoveDevice())); connect(m_Controls->m_BtnNewDevice, SIGNAL(clicked()), this, SLOT(OnClickedNewDevice())); connect(m_Controls->m_ConnectedDevices, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(OnDeviceSelectionChanged(us::ServiceReferenceU))); connect(m_Controls->m_BtnEdit, SIGNAL(clicked()), this, SLOT(OnClickedEditDevice())); } } ///////////// Methods & Slots Handling Direct Interaction ///////////////// void QmitkUSDeviceManagerWidget::OnClickedActivateDevice() { mitk::USDevice::Pointer device = m_Controls->m_ConnectedDevices->GetSelectedService(); if (device.IsNull()) { return; } if (device->GetIsActive()) { device->Deactivate(); device->Disconnect(); } else { QApplication::setOverrideCursor(Qt::WaitCursor); if (device->GetDeviceState() < mitk::USDevice::State_Connected) { device->Connect(); } if (device->GetIsConnected()) { device->Activate(); } QApplication::restoreOverrideCursor(); if (!device->GetIsActive()) { QMessageBox::warning( this, "Activation failed", "Could not activate device. Check logging for details."); } else { emit DeviceActivated(); } } // Manually reevaluate Button logic OnDeviceSelectionChanged( m_Controls->m_ConnectedDevices->GetSelectedServiceReference()); } void QmitkUSDeviceManagerWidget::OnClickedDisconnectDevice() { mitk::USDevice::Pointer device = m_Controls->m_ConnectedDevices->GetSelectedService(); if (device.IsNull()) { return; } if (device->GetIsConnected()) { device->Disconnect(); } else { if (!device->Connect()) { QMessageBox::warning( this, "Connecting failed", "Could not connect to device. Check logging for details."); } } } void QmitkUSDeviceManagerWidget::OnClickedRemoveDevice() { mitk::USDevice::Pointer device = m_Controls->m_ConnectedDevices->GetSelectedService(); + if (device.IsNull()) { return; } if (device->GetDeviceClass() == "org.mitk.modules.us.USVideoDevice") { if (device->GetIsActive()) { device->Deactivate(); } if (device->GetIsConnected()) { device->Disconnect(); } dynamic_cast(device.GetPointer()) ->UnregisterOnService(); } + else if (device->GetDeviceClass() == "IGTL Client") + { + mitk::USIGTLDevice::Pointer ultrasoundIGTLDevice = dynamic_cast(device.GetPointer()); + if (ultrasoundIGTLDevice->GetIsActive()) + { + ultrasoundIGTLDevice->Deactivate(); + } + if (ultrasoundIGTLDevice->GetIsConnected()) + { + ultrasoundIGTLDevice->Disconnect(); + } + ultrasoundIGTLDevice->UnregisterOnService(); + } } void QmitkUSDeviceManagerWidget::OnClickedNewDevice() { emit NewDeviceButtonClicked(); } void QmitkUSDeviceManagerWidget::OnClickedEditDevice() { mitk::USDevice::Pointer device = m_Controls->m_ConnectedDevices->GetSelectedService(); emit EditDeviceButtonClicked(device); } void QmitkUSDeviceManagerWidget::OnDeviceSelectionChanged( us::ServiceReferenceU reference) { if (!reference) { m_Controls->m_BtnActivate->setEnabled(false); m_Controls->m_BtnRemove->setEnabled(false); m_Controls->m_BtnEdit->setEnabled(false); return; } std::string isConnected = reference.GetProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISCONNECTED) .ToString(); std::string isActive = reference.GetProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISACTIVE) .ToString(); if (isActive.compare("false") == 0) { m_Controls->m_BtnActivate->setEnabled(true); m_Controls->m_BtnActivate->setText("Activate"); } else { m_Controls->m_BtnActivate->setEnabled(true); m_Controls->m_BtnActivate->setText("Deactivate"); } std::string deviceClass = reference.GetProperty(mitk::USDevice::GetPropertyKeys().US_PROPKEY_CLASS) .ToString(); m_Controls->m_BtnRemove->setEnabled(deviceClass == - "org.mitk.modules.us.USVideoDevice"); - m_Controls->m_BtnEdit->setEnabled((deviceClass == "org.mitk.modules.us.USVideoDevice") && (isActive.compare("false") == 0)); + "org.mitk.modules.us.USVideoDevice" || deviceClass == "IGTL Client"); + m_Controls->m_BtnEdit->setEnabled(((deviceClass == "org.mitk.modules.us.USVideoDevice") && (isActive.compare("false") == 0)) || + ((deviceClass == "IGTL Client") && (isActive.compare("false") == 0))); } void QmitkUSDeviceManagerWidget::DisconnectAllDevices() { // at the moment disconnects ALL devices. Maybe we only want to disconnect the // devices handled by this widget? us::ModuleContext* thisContext = us::GetModuleContext(); std::vector > services = thisContext->GetServiceReferences(); for (std::vector >::iterator it = services.begin(); it != services.end(); ++it) { mitk::USDevice* currentDevice = thisContext->GetService(*it); currentDevice->Disconnect(); } MITK_INFO << "Disconnected ALL US devises!"; } diff --git a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.cpp b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.cpp index 7c3dcfdbb3..9176b33562 100644 --- a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.cpp +++ b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.cpp @@ -1,811 +1,871 @@ /*=================================================================== 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. ===================================================================*/ //#define _USE_MATH_DEFINES #include // QT headers #include #include // mitk headers // itk headers #include #include const std::string QmitkUSNewVideoDeviceWidget::VIEW_ID = "org.mitk.views.QmitkUSNewVideoDeviceWidget"; QmitkUSNewVideoDeviceWidget::QmitkUSNewVideoDeviceWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = nullptr; CreateQtPartControl(this); } QmitkUSNewVideoDeviceWidget::~QmitkUSNewVideoDeviceWidget() {} //////////////////// INITIALIZATION ///////////////////// void QmitkUSNewVideoDeviceWidget::CreateQtPartControl(QWidget* parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkUSNewVideoDeviceWidgetControls; m_Controls->setupUi(parent); this->CreateConnections(); } } void QmitkUSNewVideoDeviceWidget::CreateConnections() { if (m_Controls) { // connect(m_Controls->m_BtnDone, SIGNAL(clicked()), this, // SLOT(OnClickedDone())); connect(m_Controls->m_BtnCancel, SIGNAL(clicked()), this, SLOT(OnClickedCancel())); connect(m_Controls->m_RadioDeviceSource, SIGNAL(clicked()), this, SLOT(OnDeviceTypeSelection())); connect(m_Controls->m_RadioFileSource, SIGNAL(clicked()), this, SLOT(OnDeviceTypeSelection())); connect(m_Controls->m_RadioOIGTLClientSource, SIGNAL(clicked()), this, SLOT(OnDeviceTypeSelection())); connect(m_Controls->m_RadioOIGTLServerSource, SIGNAL(clicked()), this, SLOT(OnDeviceTypeSelection())); connect(m_Controls->m_OpenFileButton, SIGNAL(clicked()), this, SLOT(OnOpenFileButtonClicked())); connect(m_Controls->m_BtnSave, SIGNAL(clicked()), this, SLOT(OnSaveButtonClicked())); connect(m_Controls->m_BtnLoadConfiguration, SIGNAL(clicked()), this, SLOT(OnLoadConfigurationButtonClicked())); //Connect buttons and functions for editing of probes connect(m_Controls->m_AddNewProbePushButton, SIGNAL(clicked()), this, SLOT(OnAddNewProbeClicked())); connect(m_Controls->m_BtnRemoveProbe, SIGNAL(clicked()), this, SLOT(OnClickedRemoveProbe())); connect(m_Controls->m_BtnRemoveDepth, SIGNAL(clicked()), this, SLOT(OnClickedRemoveDepth())); connect(m_Controls->m_BtnAddDepths, SIGNAL(clicked()), this, SLOT(OnClickedAddDepths())); connect(m_Controls->m_Probes, SIGNAL(currentTextChanged(const QString &)), this, SLOT(OnProbeChanged(const QString &))); connect(m_Controls->m_Depths, SIGNAL(currentTextChanged(const QString &)), this, SLOT(OnDepthChanged(const QString &))); connect(m_Controls->m_XSpacingSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnXSpacingSpinBoxChanged(double))); connect(m_Controls->m_YSpacingSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnYSpacingSpinBoxChanged(double))); connect(m_Controls->m_CroppingTopSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnCroppingTopSpinBoxChanged(int))); connect(m_Controls->m_CroppingRightSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnCroppingRightSpinBoxChanged(int))); connect(m_Controls->m_CroppingBottomSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnCroppingBottomSpinBoxChanged(int))); connect(m_Controls->m_CroppingLeftSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnCroppingLeftSpinBoxChanged(int))); } } ///////////// Methods & Slots Handling Direct Interaction ///////////////// void QmitkUSNewVideoDeviceWidget::OnClickedDone() { m_Active = false; // Create Device - mitk::USVideoDevice::Pointer newDevice; + mitk::USDevice::Pointer newDevice; if (m_Controls->m_RadioDeviceSource->isChecked()) { newDevice = mitk::USVideoDevice::New( m_Controls->m_DeviceSelector->value(), m_Controls->m_Manufacturer->text().toStdString(), m_Controls->m_Model->text().toStdString()); newDevice->SetComment(m_Controls->m_Comment->text().toStdString()); } else if (m_Controls->m_RadioFileSource->isChecked()) { newDevice = mitk::USVideoDevice::New( m_Controls->m_FilePathSelector->text().toStdString(), m_Controls->m_Manufacturer->text().toStdString(), m_Controls->m_Model->text().toStdString()); newDevice->SetComment(m_Controls->m_Comment->text().toStdString()); } else if (m_Controls->m_RadioOIGTLClientSource->isChecked()) { std::string host = m_Controls->m_OIGTLClientHost->text().toStdString(); int port = m_Controls->m_OIGTLClientPort->value(); // Create a new USIGTLDevice. The last parameter tells the device that it should be a client. - mitk::USIGTLDevice::Pointer device = - mitk::USIGTLDevice::New(m_Controls->m_Manufacturer->text().toStdString(), - m_Controls->m_Model->text().toStdString(), host, port, false); - device->Initialize(); - emit Finished(); - // The rest of this method does stuff that is specific to USVideoDevices, - // which we don't need. So we return directly. - return; + newDevice = mitk::USIGTLDevice::New(m_Controls->m_Manufacturer->text().toStdString(), + m_Controls->m_Model->text().toStdString(), host, port, false); + //New behavior at this position: do not return immediately as it was done in earlier MITK-versions + // The IGTL Device can have different probe configurations, as well. } else { std::string host = m_Controls->m_OIGTLServerHost->text().toStdString(); int port = m_Controls->m_OIGTLServerPort->value(); // Create a new USIGTLDevice. The last parameter tells the device that it should be a server. - mitk::USIGTLDevice::Pointer device = - mitk::USIGTLDevice::New(m_Controls->m_Manufacturer->text().toStdString(), - m_Controls->m_Model->text().toStdString(), host, port, true); - device->Initialize(); - emit Finished(); - // The rest of this method does stuff that is specific to USVideoDevices, - // which we don't need. So we return directly. - return; + newDevice = mitk::USIGTLDevice::New(m_Controls->m_Manufacturer->text().toStdString(), + m_Controls->m_Model->text().toStdString(), host, port, true); + //New behavior at this position: do not return immediately as it was done in earlier MITK-versions + // The IGTL Device can have different probe configurations, as well. } - // get USImageVideoSource from new device + //At first: only ckeck, whether it is a USImageVideoSource or not (--> if it a IGTL Client) + // Later: perhaps it would be helpful, if the IGTLMessageToUSImageFilter have a region of interest, as well. mitk::USImageVideoSource::Pointer imageSource = dynamic_cast( - newDevice->GetUSImageSource().GetPointer()); - if (!imageSource) + newDevice->GetUSImageSource().GetPointer()); + if (imageSource.IsNotNull()) { - MITK_ERROR << "There is no USImageVideoSource at the current device."; - mitkThrow() << "There is no USImageVideoSource at the current device."; - } - // Set Video Options - imageSource->SetColorOutput(!m_Controls->m_CheckGreyscale->isChecked()); + // Set Video Options + imageSource->SetColorOutput(!m_Controls->m_CheckGreyscale->isChecked()); - // If Resolution override is activated, apply it - if (m_Controls->m_CheckResolutionOverride->isChecked()) - { - int width = m_Controls->m_ResolutionWidth->value(); - int height = m_Controls->m_ResolutionHeight->value(); - imageSource->OverrideResolution(width, height); - imageSource->SetResolutionOverride(true); + // If Resolution override is activated, apply it + if (m_Controls->m_CheckResolutionOverride->isChecked()) + { + int width = m_Controls->m_ResolutionWidth->value(); + int height = m_Controls->m_ResolutionHeight->value(); + imageSource->OverrideResolution(width, height); + imageSource->SetResolutionOverride(true); + } } + if (m_Controls->m_Probes->count() != 0 ) //there are informations about the probes of the device, so create the probes { this->AddProbesToDevice(newDevice); } else //no information about the probes of the device, so set default value { mitk::USProbe::Pointer probe = mitk::USProbe::New("default"); probe->SetDepth(0); newDevice->DeleteAllProbes(); newDevice->AddNewProbe(probe); } newDevice->Initialize(); CleanUpAfterCreatingNewDevice(); emit Finished(); } void QmitkUSNewVideoDeviceWidget::OnClickedFinishedEditing() { m_Active = false; m_TargetDevice->SetManufacturer(m_Controls->m_Manufacturer->text().toStdString()); m_TargetDevice->SetName(m_Controls->m_Model->text().toStdString()); m_TargetDevice->SetComment(m_Controls->m_Comment->text().toStdString()); if (m_Controls->m_Probes->count() != 0) //there are informations about the probes of the device, so create the probes { this->AddProbesToDevice(m_TargetDevice); } else //no information about the probes of the device, so set default value { mitk::USProbe::Pointer probe = mitk::USProbe::New("default"); probe->SetDepth(0); m_TargetDevice->DeleteAllProbes(); m_TargetDevice->AddNewProbe(probe); } + //At first: only ckeck, whether it is a USImageVideoSource or not (--> if it a IGTL Client) + // Later: perhaps it would be helpful, if the IGTLMessageToUSImageFilter have a region of interest, as well. mitk::USImageVideoSource::Pointer imageSource = dynamic_cast( m_TargetDevice->GetUSImageSource().GetPointer()); - if (!imageSource) + if (imageSource.IsNotNull()) { - MITK_ERROR << "There is no USImageVideoSource at the current device."; - mitkThrow() << "There is no USImageVideoSource at the current device."; - } + // Set Video Options + imageSource->SetColorOutput(!m_Controls->m_CheckGreyscale->isChecked()); - // Set Video Options - imageSource->SetColorOutput(!m_Controls->m_CheckGreyscale->isChecked()); - - // If Resolution override is activated, apply it - if (m_Controls->m_CheckResolutionOverride->isChecked()) - { - int width = m_Controls->m_ResolutionWidth->value(); - int height = m_Controls->m_ResolutionHeight->value(); - imageSource->OverrideResolution(width, height); - imageSource->SetResolutionOverride(true); + // If Resolution override is activated, apply it + if (m_Controls->m_CheckResolutionOverride->isChecked()) + { + int width = m_Controls->m_ResolutionWidth->value(); + int height = m_Controls->m_ResolutionHeight->value(); + imageSource->OverrideResolution(width, height); + imageSource->SetResolutionOverride(true); + } } CleanUpAfterEditingOfDevice(); MITK_INFO << "Finished Editing"; emit Finished(); } void QmitkUSNewVideoDeviceWidget::OnClickedCancel() { m_TargetDevice = nullptr; m_Active = false; CleanUpAfterCreatingNewDevice(); CleanUpAfterEditingOfDevice(); emit Finished(); } void QmitkUSNewVideoDeviceWidget::OnDeviceTypeSelection() { m_Controls->m_FilePathSelector->setEnabled( m_Controls->m_RadioFileSource->isChecked()); m_Controls->m_DeviceSelector->setEnabled( m_Controls->m_RadioDeviceSource->isChecked()); m_Controls->m_OIGTLClientHost->setEnabled( m_Controls->m_RadioOIGTLClientSource->isChecked()); m_Controls->m_OIGTLClientPort->setEnabled( m_Controls->m_RadioOIGTLClientSource->isChecked()); m_Controls->m_OIGTLServerHost->setEnabled( m_Controls->m_RadioOIGTLServerSource->isChecked()); m_Controls->m_OIGTLServerPort->setEnabled( m_Controls->m_RadioOIGTLServerSource->isChecked()); } void QmitkUSNewVideoDeviceWidget::OnOpenFileButtonClicked() { QString fileName = QFileDialog::getOpenFileName(nullptr, "Open Video File"); if (fileName.isNull()) { return; } // user pressed cancel m_Controls->m_FilePathSelector->setText(fileName); m_Controls->m_RadioFileSource->setChecked(true); this->OnDeviceTypeSelection(); } ///////////////// Methods & Slots Handling Logic ////////////////////////// void QmitkUSNewVideoDeviceWidget::EditDevice(mitk::USDevice::Pointer device) { // If no VideoDevice is given, throw an exception - if (device->GetDeviceClass().compare("org.mitk.modules.us.USVideoDevice") != - 0) + if (device->GetDeviceClass().compare("org.mitk.modules.us.USVideoDevice") != 0 && + device->GetDeviceClass().compare("IGTL Client") != 0) { // TODO Alert if bad path mitkThrow() << "NewVideoDeviceWidget recieved an incompatible device type " "to edit. Type was: " << device->GetDeviceClass(); } - m_TargetDevice = static_cast(device.GetPointer()); + + m_TargetDevice = device; m_Active = true; m_ConfigProbes.clear(); m_ConfigProbes = m_TargetDevice->GetAllProbes(); ChangeUIEditingUSVideoDevice(); } void QmitkUSNewVideoDeviceWidget::CreateNewDevice() { + + //Prevent multiple calls of OnClickedDone() + disconnect(m_Controls->m_BtnDone, SIGNAL(clicked()), this, SLOT(OnClickedDone())); //Toggle functionality of Btn_Done connect(m_Controls->m_BtnDone, SIGNAL(clicked()), this, SLOT(OnClickedDone())); m_Controls->m_BtnDone->setText("Add Video Device"); //Fill Metadata with default information m_Controls->m_Manufacturer->setText("Unknown Manufacturer"); m_Controls->m_Model->setText("Unknown Model"); m_Controls->m_Comment->setText("None"); m_TargetDevice = nullptr; m_ConfigProbes.clear(); + m_ConfigProbes.clear(); m_Active = true; } /////////////////////// HOUSEHOLDING CODE /////////////////////////////// QListWidgetItem* QmitkUSNewVideoDeviceWidget::ConstructItemFromDevice( mitk::USDevice::Pointer device) { QListWidgetItem* result = new QListWidgetItem; std::string text = device->GetManufacturer() + "|" + device->GetName(); result->setText(text.c_str()); return result; } void QmitkUSNewVideoDeviceWidget::ChangeUIEditingUSVideoDevice() { for (std::vector::iterator it = m_ConfigProbes.begin(); it != m_ConfigProbes.end(); it++) { std::string probeName = (*it)->GetName(); m_Controls->m_Probes->addItem(QString::fromUtf8(probeName.data(), probeName.size())); } OnProbeChanged(m_Controls->m_Probes->currentText()); //Toggle functionality of Btn_Done m_Controls->m_BtnDone->setText("Apply Changes"); connect(m_Controls->m_BtnDone, SIGNAL(clicked()), this, SLOT(OnClickedFinishedEditing())); //Fill Metadata with Information provided by the Device selected to edit m_Controls->m_Manufacturer->setText(m_TargetDevice->GetManufacturer().c_str()); m_Controls->m_Model->setText(m_TargetDevice->GetName().c_str()); m_Controls->m_Comment->setText(m_TargetDevice->GetComment().c_str()); } void QmitkUSNewVideoDeviceWidget::OnClickedAddDepths() { if (!m_Controls->m_Probes->currentText().isEmpty()) { QString depths = m_Controls->m_AddDepths->text(); if( depths.isEmpty() ) return; std::string probename = m_Controls->m_Probes->currentText().toStdString(); mitk::USProbe::Pointer currentProbe = this->CheckIfProbeExistsAlready(probename); QStringList singleDepths = depths.split(','); for (int i = 0; i < singleDepths.size(); i++) { currentProbe->SetDepth(singleDepths.at(i).toInt()); } m_Controls->m_AddDepths->clear(); m_Controls->m_Depths->setEnabled(true); m_Controls->m_BtnRemoveDepth->setEnabled(true); OnProbeChanged(m_Controls->m_Probes->currentText()); } } void QmitkUSNewVideoDeviceWidget::OnClickedRemoveDepth() { if (!m_Controls->m_Probes->currentText().isEmpty() && !m_Controls->m_Depths->currentText().isEmpty()) { std::string probename = m_Controls->m_Probes->currentText().toStdString(); int indexOfDepthToRemove = m_Controls->m_Depths->currentIndex(); mitk::USProbe::Pointer currentProbe = this->CheckIfProbeExistsAlready(probename); currentProbe->RemoveDepth(m_Controls->m_Depths->currentText().toInt()); m_Controls->m_Depths->removeItem(indexOfDepthToRemove); if (m_Controls->m_Depths->count() == 0) { m_Controls->m_Depths->setEnabled(false); m_Controls->m_BtnRemoveDepth->setEnabled(false); this->EnableDisableSpacingAndCropping(false); } } } void QmitkUSNewVideoDeviceWidget::OnClickedRemoveProbe() { if (!m_Controls->m_Probes->currentText().isEmpty()) { std::string probename = m_Controls->m_Probes->currentText().toStdString(); int indexOfProbeToRemove = m_Controls->m_Probes->currentIndex(); m_ConfigProbes.erase(m_ConfigProbes.begin() + indexOfProbeToRemove); m_Controls->m_Probes->removeItem(indexOfProbeToRemove); if( m_Controls->m_Probes->count() == 0 ) { m_Controls->m_Probes->setEnabled(false); m_Controls->m_BtnRemoveProbe->setEnabled(false); m_Controls->m_BtnAddDepths->setEnabled(false); m_Controls->m_AddDepths->setEnabled(false); m_Controls->m_Depths->setEnabled(false); m_Controls->m_BtnRemoveDepth->setEnabled(false); this->EnableDisableSpacingAndCropping(false); } } } void QmitkUSNewVideoDeviceWidget::OnProbeChanged(const QString & probename) { if (!probename.isEmpty()) { std::string name = probename.toStdString(); mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(name); if( probe.IsNotNull() ) { std::map depths = probe->GetDepthsAndSpacing(); m_Controls->m_Depths->clear(); for (std::map::iterator it = depths.begin(); it != depths.end(); it++) { m_Controls->m_Depths->addItem(QString::number(it->first)); } this->OnDepthChanged(m_Controls->m_Depths->currentText().toInt(), probe); } } else { m_Controls->m_Depths->clear(); m_Controls->m_Depths->setEnabled(false); m_Controls->m_BtnRemoveDepth->setEnabled(false); } } void QmitkUSNewVideoDeviceWidget::OnDepthChanged(int depth, mitk::USProbe::Pointer probe) { if (m_Controls->m_Depths->count() == 0) { m_Controls->m_Depths->setEnabled(false); m_Controls->m_BtnRemoveDepth->setEnabled(false); this->EnableDisableSpacingAndCropping(false); return; } if (probe.IsNotNull()) { mitk::Vector3D spacing = probe->GetSpacingForGivenDepth(depth); m_Controls->m_XSpacingSpinBox->setValue(spacing[0]); m_Controls->m_YSpacingSpinBox->setValue(spacing[1]); mitk::USProbe::USProbeCropping cropping = probe->GetProbeCropping(); m_Controls->m_CroppingTopSpinBox->setValue(cropping.top); m_Controls->m_CroppingRightSpinBox->setValue(cropping.right); m_Controls->m_CroppingBottomSpinBox->setValue(cropping.bottom); m_Controls->m_CroppingLeftSpinBox->setValue(cropping.left); this->EnableDisableSpacingAndCropping(true); m_Controls->m_Depths->setEnabled(true); m_Controls->m_BtnRemoveDepth->setEnabled(true); m_Controls->m_AddDepths->setEnabled(true); m_Controls->m_BtnAddDepths->setEnabled(true); m_Controls->m_Probes->setEnabled(true); m_Controls->m_BtnRemoveProbe->setEnabled(true); } } void QmitkUSNewVideoDeviceWidget::OnDepthChanged(const QString &depth) { MITK_INFO << "OnDepthChanged(int, mitk::USProbe)"; if( depth.isEmpty() ) { this->EnableDisableSpacingAndCropping(false); return; } QString probeName = m_Controls->m_Probes->currentText(); this->OnDepthChanged(depth.toInt(), this->CheckIfProbeExistsAlready(probeName.toStdString()) ); } void QmitkUSNewVideoDeviceWidget::OnSaveButtonClicked() { QString fileName = QFileDialog::getSaveFileName(nullptr, "Save Configuration ...", "", "XML files (*.xml)"); if( fileName.isNull() ) { return; } // user pressed cancel mitk::USDeviceWriterXML deviceWriter; deviceWriter.SetFilename(fileName.toStdString()); - mitk::USDeviceReaderXML::USVideoDeviceConfigData config; - this->CollectUltrasoundVideoDeviceConfigInformation(config); + mitk::USDeviceReaderXML::USDeviceConfigData config; + this->CollectUltrasoundDeviceConfigInformation(config); - if (!deviceWriter.WriteUltrasoundVideoDeviceConfiguration(config)) + if (!deviceWriter.WriteUltrasoundDeviceConfiguration(config)) { QMessageBox msgBox; msgBox.setText("Error when writing the configuration to the selected file. Could not write device information."); msgBox.exec(); return; } } void QmitkUSNewVideoDeviceWidget::OnLoadConfigurationButtonClicked() { QString fileName = QFileDialog::getOpenFileName(this, "Open ultrasound device configuration ..."); if (fileName.isNull()) { return; } // user pressed cancel mitk::USDeviceReaderXML deviceReader; deviceReader.SetFilename(fileName.toStdString()); if (!deviceReader.ReadUltrasoundDeviceConfiguration()) { QMessageBox msgBox; msgBox.setText("Error when parsing the selected file. Could not load stored device information."); msgBox.exec(); return; } - mitk::USDeviceReaderXML::USVideoDeviceConfigData config = deviceReader.GetUSVideoDeviceConfigData(); + mitk::USDeviceReaderXML::USDeviceConfigData config = deviceReader.GetUSDeviceConfigData(); if( config.fileversion == 1.0 ) { if (config.deviceType.compare("video") == 0) { //Fill info in metadata groupbox: m_Controls->m_DeviceName->setText(QString::fromStdString(config.deviceName)); m_Controls->m_Manufacturer->setText(QString::fromStdString(config.manufacturer)); m_Controls->m_Model->setText(QString::fromStdString(config.model)); m_Controls->m_Comment->setText(QString::fromStdString(config.comment)); //Fill info about video source: m_Controls->m_DeviceSelector->setValue(config.sourceID); m_Controls->m_FilePathSelector->setText(QString::fromStdString(config.filepathVideoSource)); //Fill video options: m_Controls->m_CheckGreyscale->setChecked(config.useGreyscale); //Fill override options: m_Controls->m_CheckResolutionOverride->setChecked(config.useResolutionOverride); m_Controls->m_ResolutionWidth->setValue(config.resolutionWidth); m_Controls->m_ResolutionHeight->setValue(config.resolutionHeight); //Fill information about probes: m_ConfigProbes.clear(); m_ConfigProbes = config.probes; m_Controls->m_Probes->clear(); m_Controls->m_ProbeNameLineEdit->clear(); m_Controls->m_AddDepths->clear(); m_Controls->m_Depths->clear(); for( size_t index = 0; index < m_ConfigProbes.size(); ++index) { m_Controls->m_Probes->addItem(QString::fromStdString(config.probes.at(index)->GetName())); } this->OnProbeChanged(m_Controls->m_Probes->currentText()); } + else if (config.deviceType.compare("oigtl") == 0) + { + //Fill info in metadata groupbox: + m_Controls->m_DeviceName->setText(QString::fromStdString(config.deviceName)); + m_Controls->m_Manufacturer->setText(QString::fromStdString(config.manufacturer)); + m_Controls->m_Model->setText(QString::fromStdString(config.model)); + m_Controls->m_Comment->setText(QString::fromStdString(config.comment)); + + //Fill info about OpenIGTLink video source: + if (config.server) + { + m_Controls->m_RadioOIGTLServerSource->setChecked(true); + m_Controls->m_OIGTLServerHost->setText(QString::fromStdString(config.host)); + m_Controls->m_OIGTLServerPort->setValue(config.port); + } + else + { + m_Controls->m_RadioOIGTLClientSource->setChecked(true); + m_Controls->m_OIGTLClientHost->setText(QString::fromStdString(config.host)); + m_Controls->m_OIGTLClientPort->setValue(config.port); + } + this->OnDeviceTypeSelection(); + + //Fill video options: + m_Controls->m_CheckGreyscale->setChecked(config.useGreyscale); + + //Fill override options: + m_Controls->m_CheckResolutionOverride->setChecked(config.useResolutionOverride); + m_Controls->m_ResolutionWidth->setValue(config.resolutionWidth); + m_Controls->m_ResolutionHeight->setValue(config.resolutionHeight); + + //Fill information about probes: + m_ConfigProbes.clear(); + m_ConfigProbes = config.probes; + + m_Controls->m_Probes->clear(); + m_Controls->m_ProbeNameLineEdit->clear(); + m_Controls->m_AddDepths->clear(); + m_Controls->m_Depths->clear(); + + for (size_t index = 0; index < m_ConfigProbes.size(); ++index) + { + m_Controls->m_Probes->addItem(QString::fromStdString(config.probes.at(index)->GetName())); + } + this->OnProbeChanged(m_Controls->m_Probes->currentText()); + } else { MITK_WARN << "Unknown device type detected. The device type must be of type |video|"; } } else { MITK_WARN << "Unknown fileversion. Only fileversion 1.0 is known to the system."; } } void QmitkUSNewVideoDeviceWidget::OnAddNewProbeClicked() { QString probeName = m_Controls->m_ProbeNameLineEdit->text(); probeName = probeName.trimmed(); if (probeName.isEmpty()) { m_Controls->m_ProbeNameLineEdit->clear(); return; } if( this->CheckIfProbeExistsAlready(probeName.toStdString() ) != nullptr ) { QMessageBox msgBox; msgBox.setText("Probe name already exists. Please choose another name for the probe."); msgBox.exec(); m_Controls->m_ProbeNameLineEdit->clear(); } else { mitk::USProbe::Pointer newProbe = mitk::USProbe::New(probeName.toStdString()); m_ConfigProbes.push_back(newProbe); m_Controls->m_Probes->addItem(QString::fromStdString(probeName.toStdString())); m_Controls->m_Probes->setEnabled(true); m_Controls->m_BtnRemoveProbe->setEnabled(true); m_Controls->m_BtnAddDepths->setEnabled(true); m_Controls->m_AddDepths->setEnabled(true); m_Controls->m_ProbeNameLineEdit->clear(); } } void QmitkUSNewVideoDeviceWidget::OnXSpacingSpinBoxChanged(double value) { MITK_INFO << "Changing x-spacing to: " << value; QString probeName = m_Controls->m_Probes->currentText(); int depth = m_Controls->m_Depths->currentText().toInt(); mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(probeName.toStdString()); if (probe.IsNull()) { QMessageBox msgBox; msgBox.setText("An error occurred when changing the spacing. \ The specified probe does not exist. \ Please restart the configuration process."); msgBox.exec(); return; } mitk::Vector3D spacing = probe->GetSpacingForGivenDepth(depth); spacing[0] = value; probe->SetSpacingForGivenDepth(depth, spacing); } void QmitkUSNewVideoDeviceWidget::OnYSpacingSpinBoxChanged(double value) { MITK_INFO << "Changing y-spacing to: " << value; QString probeName = m_Controls->m_Probes->currentText(); int depth = m_Controls->m_Depths->currentText().toInt(); mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(probeName.toStdString()); if (probe.IsNull()) { QMessageBox msgBox; msgBox.setText("An error occurred when changing the spacing. \ The specified probe does not exist. \ Please restart the configuration process."); msgBox.exec(); return; } mitk::Vector3D spacing = probe->GetSpacingForGivenDepth(depth); spacing[1] = value; probe->SetSpacingForGivenDepth(depth, spacing); } void QmitkUSNewVideoDeviceWidget::OnCroppingTopSpinBoxChanged(int value) { MITK_INFO << "Changing cropping top to: " << value; QString probeName = m_Controls->m_Probes->currentText(); mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(probeName.toStdString()); if (probe.IsNull()) { QMessageBox msgBox; msgBox.setText("An error occurred when changing the probe cropping. \ The specified probe does not exist. \ Please restart the configuration process."); msgBox.exec(); return; } mitk::USProbe::USProbeCropping cropping = probe->GetProbeCropping(); probe->SetProbeCropping(value, cropping.bottom, cropping.left, cropping.right); } void QmitkUSNewVideoDeviceWidget::OnCroppingRightSpinBoxChanged(int value) { MITK_INFO << "Changing cropping right to: " << value; QString probeName = m_Controls->m_Probes->currentText(); mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(probeName.toStdString()); if (probe.IsNull()) { QMessageBox msgBox; msgBox.setText("An error occurred when changing the probe cropping. \ The specified probe does not exist. \ Please restart the configuration process."); msgBox.exec(); return; } mitk::USProbe::USProbeCropping cropping = probe->GetProbeCropping(); probe->SetProbeCropping(cropping.top, cropping.bottom, cropping.left, value); } void QmitkUSNewVideoDeviceWidget::OnCroppingBottomSpinBoxChanged(int value) { MITK_INFO << "Changing cropping bottom to: " << value; QString probeName = m_Controls->m_Probes->currentText(); mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(probeName.toStdString()); if (probe.IsNull()) { QMessageBox msgBox; msgBox.setText("An error occurred when changing the probe cropping. \ The specified probe does not exist. \ Please restart the configuration process."); msgBox.exec(); return; } mitk::USProbe::USProbeCropping cropping = probe->GetProbeCropping(); probe->SetProbeCropping(cropping.top, value, cropping.left, cropping.right); } void QmitkUSNewVideoDeviceWidget::OnCroppingLeftSpinBoxChanged(int value) { MITK_INFO << "Changing cropping left to: " << value; QString probeName = m_Controls->m_Probes->currentText(); mitk::USProbe::Pointer probe = this->CheckIfProbeExistsAlready(probeName.toStdString()); if (probe.IsNull()) { QMessageBox msgBox; msgBox.setText("An error occurred when changing the probe cropping. \ The specified probe does not exist. \ Please restart the configuration process."); msgBox.exec(); return; } mitk::USProbe::USProbeCropping cropping = probe->GetProbeCropping(); probe->SetProbeCropping(cropping.top, cropping.bottom, value, cropping.right); } void QmitkUSNewVideoDeviceWidget::CleanUpAfterCreatingNewDevice() { disconnect(m_Controls->m_BtnDone, SIGNAL(clicked()), this, SLOT(OnClickedDone())); m_Controls->m_Probes->clear(); m_Controls->m_Depths->clear(); m_Controls->m_AddDepths->clear(); m_Controls->m_ProbeNameLineEdit->clear(); m_ConfigProbes.clear(); } void QmitkUSNewVideoDeviceWidget::CleanUpAfterEditingOfDevice() { disconnect(m_Controls->m_BtnDone, SIGNAL(clicked()), this, SLOT(OnClickedFinishedEditing())); m_Controls->m_Probes->clear(); m_Controls->m_Depths->clear(); m_Controls->m_AddDepths->clear(); m_ConfigProbes.clear(); } -void QmitkUSNewVideoDeviceWidget::AddProbesToDevice(mitk::USVideoDevice::Pointer device) +void QmitkUSNewVideoDeviceWidget::AddProbesToDevice(mitk::USDevice::Pointer device) { device->DeleteAllProbes(); for( std::vector::iterator it = m_ConfigProbes.begin(); it != m_ConfigProbes.end(); it++) { if ((*it)->IsDepthAndSpacingEmpty()) { (*it)->SetDepth(0); } device->AddNewProbe((*it)); } } mitk::USProbe::Pointer QmitkUSNewVideoDeviceWidget::CheckIfProbeExistsAlready(const std::string &probeName) { for( std::vector::iterator it = m_ConfigProbes.begin(); it != m_ConfigProbes.end(); it++ ) { if( probeName.compare((*it)->GetName()) == 0) return (*it); } return nullptr; //no matching probe was found so nullptr is returned } -void QmitkUSNewVideoDeviceWidget::CollectUltrasoundVideoDeviceConfigInformation(mitk::USDeviceReaderXML::USVideoDeviceConfigData &config) +void QmitkUSNewVideoDeviceWidget::CollectUltrasoundDeviceConfigInformation(mitk::USDeviceReaderXML::USDeviceConfigData &config) { config.fileversion = 1.0; - config.deviceType = "video"; + if (m_Controls->m_RadioDeviceSource->isChecked() || m_Controls->m_RadioFileSource->isChecked()) + { + //Fill info about video source: + config.deviceType = "video"; + config.sourceID = m_Controls->m_DeviceSelector->value(); + config.filepathVideoSource = m_Controls->m_FilePathSelector->text().toStdString(); + } + else + { + config.deviceType = "oigtl"; + if (m_Controls->m_RadioOIGTLServerSource->isChecked()) + { + config.server = true; + config.host = m_Controls->m_OIGTLServerHost->text().toStdString(); + config.port = m_Controls->m_OIGTLServerPort->value(); + } + else + { + config.server = false; + config.host = m_Controls->m_OIGTLClientHost->text().toStdString(); + config.port = m_Controls->m_OIGTLClientPort->value(); + } + } //Fill info in metadata groupbox: config.deviceName = m_Controls->m_DeviceName->text().toStdString(); config.manufacturer = m_Controls->m_Manufacturer->text().toStdString(); config.model = m_Controls->m_Model->text().toStdString(); config.comment = m_Controls->m_Comment->text().toStdString(); - //Fill info about video source: - config.sourceID = m_Controls->m_DeviceSelector->value(); - config.filepathVideoSource = m_Controls->m_FilePathSelector->text().toStdString(); - //Fill video options: config.useGreyscale = m_Controls->m_CheckGreyscale->isChecked(); //Fill override options: config.useResolutionOverride = m_Controls->m_CheckResolutionOverride->isChecked(); config.resolutionWidth = m_Controls->m_ResolutionWidth->value(); config.resolutionHeight = m_Controls->m_ResolutionHeight->value(); //Fill information about probes: config.probes = m_ConfigProbes; } void QmitkUSNewVideoDeviceWidget::EnableDisableSpacingAndCropping(bool enable) { m_Controls->m_XSpacingSpinBox->setEnabled(enable); m_Controls->m_YSpacingSpinBox->setEnabled(enable); m_Controls->m_XSpacingLabel->setEnabled(enable); m_Controls->m_YSpacingLabel->setEnabled(enable); m_Controls->m_CroppingTopSpinBox->setEnabled(enable); m_Controls->m_CroppingRightSpinBox->setEnabled(enable); m_Controls->m_CroppingBottomSpinBox->setEnabled(enable); m_Controls->m_CroppingLeftSpinBox->setEnabled(enable); m_Controls->m_CroppingTopLabel->setEnabled(enable); m_Controls->m_CroppingBottomLabel->setEnabled(enable); m_Controls->m_CroppingLeftLabel->setEnabled(enable); m_Controls->m_CroppingRightLabel->setEnabled(enable); } diff --git a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.h b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.h index 6c7aef6b49..78e45d50cb 100644 --- a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.h +++ b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.h @@ -1,169 +1,169 @@ /*=================================================================== 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 _QmitkUSNewVideoDeviceWidget_H_INCLUDED #define _QmitkUSNewVideoDeviceWidget_H_INCLUDED #include "MitkUSUIExports.h" #include "ui_QmitkUSNewVideoDeviceWidgetControls.h" #include "mitkUSVideoDevice.h" #include "mitkUSIGTLDevice.h" #include "mitkUSDeviceReaderXML.h" //QT headers #include #include //mitk header /** * @brief This Widget enables the USer to create and connect Video Devices. * * @ingroup USUI */ class MITKUSUI_EXPORT QmitkUSNewVideoDeviceWidget :public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkUSNewVideoDeviceWidget(QWidget* p = nullptr, Qt::WindowFlags f1 = nullptr); ~QmitkUSNewVideoDeviceWidget() override; /* @brief This method is part of the widget an needs not to be called seperately. */ virtual void CreateQtPartControl(QWidget *parent); /* @brief This method is part of the widget an needs not to be called seperately. (Creation of the connections of main and control widget.)*/ virtual void CreateConnections(); signals: void Finished(); public slots: /* \brief Activates the widget and displays the given device's Data to edit. */ void EditDevice(mitk::USDevice::Pointer device); /* \brief Activates the widget with fields empty. */ void CreateNewDevice(); protected slots: /* \brief Called, when the the user clicks the "Done" button (Labeled either "Add Device" or "Edit Device", depending on the situation. */ void OnClickedDone(); void OnClickedFinishedEditing(); /* \brief Called, when the button "Cancel" was clicked */ void OnClickedCancel(); /* \brief Called, when the Use selects one of the Radiobuttons */ void OnDeviceTypeSelection(); void OnOpenFileButtonClicked(); void OnClickedRemoveProbe(); void OnClickedRemoveDepth(); void OnClickedAddDepths(); void OnProbeChanged(const QString & probename); void OnDepthChanged(int depth, mitk::USProbe::Pointer probe); void OnDepthChanged(const QString &depth); void OnSaveButtonClicked(); void OnLoadConfigurationButtonClicked(); void OnAddNewProbeClicked(); void OnXSpacingSpinBoxChanged(double value); void OnYSpacingSpinBoxChanged(double value); void OnCroppingTopSpinBoxChanged(int value); void OnCroppingRightSpinBoxChanged(int value); void OnCroppingBottomSpinBoxChanged(int value); void OnCroppingLeftSpinBoxChanged(int value); protected: Ui::QmitkUSNewVideoDeviceWidgetControls* m_Controls; ///< member holding the UI elements of this widget /* \brief Constructs a ListItem from the given device for display in the list of active devices */ QListWidgetItem* ConstructItemFromDevice(mitk::USDevice::Pointer device); void ChangeUIEditingUSVideoDevice(); void CleanUpAfterEditingOfDevice(); void CleanUpAfterCreatingNewDevice(); - void AddProbesToDevice(mitk::USVideoDevice::Pointer device); + void AddProbesToDevice(mitk::USDevice::Pointer device); mitk::USProbe::Pointer CheckIfProbeExistsAlready(const std::string &probe); - void CollectUltrasoundVideoDeviceConfigInformation(mitk::USDeviceReaderXML::USVideoDeviceConfigData &config); + void CollectUltrasoundDeviceConfigInformation(mitk::USDeviceReaderXML::USDeviceConfigData &config); /** * \brief Enables or disables the GUI elements of the spacing and cropping options. * \param enable If true: the GUI elements are enabled. If false: elements are disabled. */ void EnableDisableSpacingAndCropping(bool enable); /* \brief Displays whether this widget is active or not. It gets activated by either sending a Signal to * the "CreateNewDevice" Slot or to the "EditDevice" Slot. If the user finishes editing the device, a * "EditingComplete" Signal is sent, and the widget is set to inactive again. Clicking Cancel also * deactivates it. */ bool m_Active; /** * \brief This is the device to edit. It is either the device transmitted in the "EditDevice" signal, or a new one - * if the "CreateNewDevice slot was called. + * if the "CreateNewDevice slot was called. As device type: either mitkUSVideoDevice or mitkUSIGTLDevice */ - mitk::USVideoDevice::Pointer m_TargetDevice; + mitk::USDevice::Pointer m_TargetDevice; /** * \brief The config probes are used to have a possibility to configure ultrasound probes without having an existing * created USVideoDevice yet. */ std::vector m_ConfigProbes; }; #endif // _QmitkUSNewVideoDeviceWidget_H_INCLUDED diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index 4446b8ab1a..f874d7dd38 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,116 +1,116 @@ # Plug-ins must be ordered according to their dependencies set(MITK_PLUGINS org.blueberry.core.runtime:ON org.blueberry.core.expressions:OFF org.blueberry.core.commands:OFF org.blueberry.core.jobs:OFF org.blueberry.ui.qt:OFF org.blueberry.ui.qt.help:ON org.blueberry.ui.qt.log:ON org.blueberry.ui.qt.objectinspector:OFF #org.blueberry.test:ON #org.blueberry.uitest:ON #Testing/org.blueberry.core.runtime.tests:ON #Testing/org.blueberry.osgi.tests:ON org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.mxnmultiwidgeteditor:OFF org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.chartExample:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.datastorageviewertest:OFF org.mitk.gui.qt.properties:ON org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.dicominspector:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.diffusionimaging.connectomics:OFF org.mitk.gui.qt.diffusionimaging.denoising:OFF org.mitk.gui.qt.diffusionimaging.fiberfox:OFF org.mitk.gui.qt.diffusionimaging.fiberprocessing:OFF org.mitk.gui.qt.diffusionimaging.ivim:OFF org.mitk.gui.qt.diffusionimaging.odfpeaks:OFF org.mitk.gui.qt.diffusionimaging.partialvolume:OFF org.mitk.gui.qt.diffusionimaging.preprocessing:OFF org.mitk.gui.qt.diffusionimaging.reconstruction:OFF org.mitk.gui.qt.diffusionimaging.registration:OFF org.mitk.gui.qt.diffusionimaging.tractography:OFF org.mitk.gui.qt.diffusionimaging.python:OFF org.mitk.gui.qt.dosevisualization:OFF org.mitk.gui.qt.geometrytools:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF org.mitk.gui.qt.lasercontrol:OFF org.mitk.gui.qt.openigtlink:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.viewnavigator:OFF org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.pointsetinteractionmultispectrum:OFF org.mitk.gui.qt.python:OFF org.mitk.gui.qt.remeshing:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.aicpregistration:OFF org.mitk.gui.qt.renderwindowmanager:OFF org.mitk.gui.qt.semanticrelations:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.tubegraph:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.photoacoustics.pausviewer:OFF org.mitk.gui.qt.photoacoustics.pausmotioncompensation:OFF org.mitk.gui.qt.photoacoustics.imageprocessing:OFF org.mitk.gui.qt.photoacoustics.simulation:OFF org.mitk.gui.qt.photoacoustics.spectralunmixing:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF org.mitk.gui.qt.eventrecorder:OFF org.mitk.gui.qt.xnat:OFF - org.mitk.gui.qt.igt.app.echotrack:OFF + org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation:OFF org.mitk.gui.qt.spectrocamrecorder:OFF org.mitk.gui.qt.classificationsegmentation:OFF org.mitk.gui.qt.overlaymanager:OFF org.mitk.gui.qt.igt.app.hummelprotocolmeasurements:OFF org.mitk.gui.qt.multilabelsegmentation:OFF org.mitk.matchpoint.core.helper:OFF org.mitk.gui.qt.matchpoint.algorithm.browser:OFF org.mitk.gui.qt.matchpoint.algorithm.control:OFF org.mitk.gui.qt.matchpoint.algorithm.batch:OFF org.mitk.gui.qt.matchpoint.mapper:OFF org.mitk.gui.qt.matchpoint.framereg:OFF org.mitk.gui.qt.matchpoint.visualizer:OFF org.mitk.gui.qt.matchpoint.evaluator:OFF org.mitk.gui.qt.matchpoint.manipulator:OFF org.mitk.gui.qt.preprocessing.resampling:OFF org.mitk.gui.qt.radiomics:OFF org.mitk.gui.qt.cest:OFF org.mitk.gui.qt.fit.demo:OFF org.mitk.gui.qt.fit.inspector:OFF org.mitk.gui.qt.fit.genericfitting:OFF org.mitk.gui.qt.pharmacokinetics.mri:OFF org.mitk.gui.qt.pharmacokinetics.pet:OFF org.mitk.gui.qt.pharmacokinetics.simulation:OFF org.mitk.gui.qt.pharmacokinetics.curvedescriptor:OFF org.mitk.gui.qt.pharmacokinetics.concentration.mri:OFF ) diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationMarkerPlacement.ui b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationMarkerPlacement.ui deleted file mode 100644 index ceb1ffc701..0000000000 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationMarkerPlacement.ui +++ /dev/null @@ -1,123 +0,0 @@ - - - QmitkUSNavigationMarkerPlacement - - - - 0 - 0 - 443 - 146 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - Qt::Horizontal - - - - - - - - - Enable Navigation Render Window Layout with RenderWindow - - - true - - - - - - - 1 - - - 3 - - - - - - - Refresh view - - - - - - - - - - - Start New Experiment - - - - - - - false - - - Finish Experiment - - - - - - - - 20 - 20 - - - - - - - - - - - - - - QmitkUSNavigationProcessWidget - QWidget -
src/internal/Widgets/QmitkUSNavigationProcessWidget.h
- 1 -
-
- - - - OnStartExperiment() - OnFinishExperiment() - -
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 deleted file mode 100644 index 0ef68154c7..0000000000 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.cpp +++ /dev/null @@ -1,557 +0,0 @@ -/*=================================================================== - -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->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->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->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) -{ - 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 deleted file mode 100644 index 1a78fd3998..0000000000 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.h +++ /dev/null @@ -1,179 +0,0 @@ -/*=================================================================== - -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); - - /** - * \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 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 diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.ui b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.ui deleted file mode 100644 index 5526f413c9..0000000000 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.ui +++ /dev/null @@ -1,203 +0,0 @@ - - - QmitkUSNavigationProcessWidget - - - - 0 - 0 - 465 - 757 - - - - Form - - - - - - - font-size: 10pt; - font-weight: bold; - - - - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - 0 - - - - - - - - - - - - - false - - - Open Preferences - - - Preferences - - - - :/USNavigation/preferences.png:/USNavigation/preferences.png - - - - - - - false - - - false - - - Restart the Current Step - - - &Restart Step - - - - :/USNavigation/restart.png:/USNavigation/restart.png - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - Go to Previous Step - - - &Prev - - - - :/USNavigation/go-previous.png:/USNavigation/go-previous.png - - - - - - - false - - - Go to Next Step - - - &Next - - - - :/USNavigation/go-next.png:/USNavigation/go-next.png - - - - - - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Settings</span></p></body></html> - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - Save - - - - :/USNavigation/document-save.png:/USNavigation/document-save.png - - - - - - - Cancel - - - - :/USNavigation/restart.png:/USNavigation/restart.png - - - - - - - - - - - - - - - - OnNextButtonClicked() - OnPreviousButtonClicked() - OnRestartStepButtonClicked() - OnTabChanged(int) - - diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/CMakeLists.txt b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/CMakeLists.txt similarity index 72% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/CMakeLists.txt rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/CMakeLists.txt index 28dfd3d235..6581e2a790 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/CMakeLists.txt @@ -1,16 +1,16 @@ -project(org_mitk_gui_qt_igt_app_echotrack) +project(org_mitk_gui_qt_igt_app_ultrasoundtrackingnavigation) mitk_create_plugin( - EXPORT_DIRECTIVE IGTAPPECHOTRACK_EXPORT + EXPORT_DIRECTIVE IGTAPPUSTRACKINGNAVIGATION_EXPORT EXPORTED_INCLUDE_SUFFIXES src PACKAGE_DEPENDS CTK Poco - MODULE_DEPENDS MitkUSUI MitkUSNavigation MitkIGTUI MitkSceneSerialization MitkContourModel + MODULE_DEPENDS MitkUSUI MitkUSNavigation MitkIGTUI MitkSceneSerialization MitkContourModel ITKLabelMap ) #usFunctionAddResources(TARGET ${PLUGIN_TARGET} # MODULE_NAME liborg_mitk_gui_qt_usnavigation # WORKING_DIRECTORY resources # FILES Interactions/USPointMarkInteractions.xml # Interactions/USZoneInteractions.xml # Interactions/USZoneInteractionsHold.xml #) diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/documentation/UserManual/Manual.dox similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/documentation/UserManual/Manual.dox rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/documentation/UserManual/Manual.dox diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/documentation/UserManual/icon.xpm b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/documentation/UserManual/icon.xpm similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/documentation/UserManual/icon.xpm rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/documentation/UserManual/icon.xpm diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/documentation/doxygen/modules.dox similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/documentation/doxygen/modules.dox rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/documentation/doxygen/modules.dox diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/files.cmake b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/files.cmake similarity index 94% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/files.cmake rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/files.cmake index a980a60ba8..51339925f7 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/files.cmake +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/files.cmake @@ -1,136 +1,136 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES org_mbi_gui_qt_usnavigation_Activator.cpp #USNavigation.cpp //not functional anymore. Delete code? QmitkUltrasoundCalibration.cpp QmitkUSNavigationMarkerPlacement.cpp QmitkUSNavigationPerspective.cpp mitkUSTargetPlacementQualityCalculator.cpp QmitkUSZonesDataModel.cpp QmitkUSNavigationCalibrationsDataModel.cpp QmitkUSZoneManagementColorDialogDelegate.cpp QmitkUSNavigationCalibrationRemoveDelegate.cpp QmitkUSNavigationCalibrationUpdateDepthDelegate.cpp Interactors/mitkUSZonesInteractor.cpp Interactors/mitkUSPointMarkInteractor.cpp Widgets/QmitkUSCombinedModalityCreationWidget.cpp Widgets/QmitkUSCombinedModalityEditWidget.cpp Widgets/QmitkUSNavigationFreezeButton.cpp - Widgets/QmitkUSNavigationProcessWidget.cpp Widgets/QmitkUSNavigationZoneDistancesWidget.cpp Widgets/QmitkUSZoneManagementWidget.cpp Widgets/QmitkZoneProgressBar.cpp NavigationStepWidgets/QmitkUSAbstractNavigationStep.cpp NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.cpp NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.cpp NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.cpp NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.cpp NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.cpp + NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.cpp SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.cpp SettingsWidgets/QmitkUSNavigationAbstractSettingsWidget.cpp Filter/mitkUSNavigationTargetOcclusionFilter.cpp Filter/mitkUSNavigationTargetUpdateFilter.cpp Filter/mitkUSNavigationTargetIntersectionFilter.cpp + Filter/mitkFloatingImageToUltrasoundRegistrationFilter.cpp IO/mitkUSNavigationCombinedModalityPersistence.cpp IO/mitkUSNavigationLoggingBackend.cpp IO/mitkUSNavigationExperimentLogging.cpp IO/mitkUSNavigationStepTimer.cpp ) set(UI_FILES #src/internal/USNavigationControls.ui //not functional anymore. Delete code? src/internal/QmitkUltrasoundCalibrationControls.ui src/internal/QmitkUSNavigationMarkerPlacement.ui src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.ui src/internal/Widgets/QmitkUSCombinedModalityEditWidget.ui - src/internal/Widgets/QmitkUSNavigationProcessWidget.ui src/internal/Widgets/QmitkUSZoneManagementWidget.ui src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.ui src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.ui src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.ui src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.ui src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.ui src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.ui src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.ui + src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.ui src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.ui ) set(MOC_H_FILES src/internal/org_mbi_gui_qt_usnavigation_Activator.h - #src/internal/USNavigation.h //not functional anymore. Delete code? src/internal/QmitkUltrasoundCalibration.h src/internal/QmitkUSNavigationMarkerPlacement.h src/internal/QmitkUSZonesDataModel.h src/internal/QmitkUSNavigationCalibrationsDataModel.h src/internal/QmitkUSZoneManagementColorDialogDelegate.h src/internal/QmitkUSNavigationCalibrationRemoveDelegate.h src/internal/QmitkUSNavigationCalibrationUpdateDepthDelegate.h src/internal/QmitkUSNavigationPerspective.h src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.h src/internal/Widgets/QmitkUSCombinedModalityEditWidget.h src/internal/Widgets/QmitkUSNavigationFreezeButton.h - src/internal/Widgets/QmitkUSNavigationProcessWidget.h src/internal/Widgets/QmitkUSNavigationZoneDistancesWidget.h src/internal/Widgets/QmitkUSZoneManagementWidget.h src/internal/Widgets/QmitkZoneProgressBar.h src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.h src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.h src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.h src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.h src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h + src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.h src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.h src/internal/SettingsWidgets/QmitkUSNavigationAbstractSettingsWidget.h ) # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench set(CACHED_RESOURCE_FILES resources/icon_US_navigation.svg resources/icon_US_calibration.svg plugin.xml ) # list of Qt .qrc files which contain additional resources # specific to this plugin set(QRC_FILES resources/USNavigation.qrc ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) set(RESOURCE_FILES Interactions/USPointMarkInteractions.xml Interactions/USZoneInteractions.xml Interactions/USZoneInteractionsHold.xml ) diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/manifest_headers.cmake similarity index 78% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/manifest_headers.cmake rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/manifest_headers.cmake index dd435aea13..32789a6fdc 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/manifest_headers.cmake @@ -1,5 +1,5 @@ -set(Plugin-Name "IGT APP: EchoTrack") +set(Plugin-Name "IGT APP: UltrasoundTracking Navigation") set(Plugin-Version "0.1") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "http://www.mitk.org") set(Require-Plugin org.mitk.gui.qt.common org.mitk.gui.qt.stdmultiwidgeteditor) diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/plugin.xml b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/plugin.xml similarity index 90% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/plugin.xml rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/plugin.xml index d3fd0791ff..dc006770cb 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/plugin.xml +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/plugin.xml @@ -1,26 +1,26 @@ diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/Interactions/USPointMarkInteractions.xml b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/Interactions/USPointMarkInteractions.xml similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/Interactions/USPointMarkInteractions.xml rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/Interactions/USPointMarkInteractions.xml diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/Interactions/USZoneInteractions.xml b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/Interactions/USZoneInteractions.xml similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/Interactions/USZoneInteractions.xml rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/Interactions/USZoneInteractions.xml diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/Interactions/USZoneInteractionsHold.xml b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/Interactions/USZoneInteractionsHold.xml similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/Interactions/USZoneInteractionsHold.xml rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/Interactions/USZoneInteractionsHold.xml diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/USNavigation.qrc b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/USNavigation.qrc similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/USNavigation.qrc rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/USNavigation.qrc diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/accept.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/accept.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/accept.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/accept.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/document-open.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/document-open.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/document-open.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/document-open.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/document-save.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/document-save.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/document-save.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/document-save.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/go-next.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/go-next.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/go-next.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/go-next.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/go-previous.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/go-previous.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/go-previous.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/go-previous.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon.xpm b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon.xpm similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon.xpm rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon.xpm diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon2.xpm b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon2.xpm similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon2.xpm rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon2.xpm diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon2_old.xpm b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon2_old.xpm similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon2_old.xpm rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon2_old.xpm diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon_US_calibration.svg b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon_US_calibration.svg similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon_US_calibration.svg rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon_US_calibration.svg diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon_US_navigation.svg b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon_US_navigation.svg similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon_US_navigation.svg rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon_US_navigation.svg diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon_calibration.xpm b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon_calibration.xpm similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon_calibration.xpm rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon_calibration.xpm diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon_calibration_old.xpm b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon_calibration_old.xpm similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/icon_calibration_old.xpm rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/icon_calibration_old.xpm diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/minus.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/minus.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/minus.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/minus.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/plus.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/plus.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/plus.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/plus.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/preferences.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/preferences.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/preferences.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/preferences.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/process-stop.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/process-stop.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/process-stop.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/process-stop.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/record-gray.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/record-gray.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/record-gray.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/record-gray.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/record.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/record.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/record.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/record.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/restart.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/restart.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/restart.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/restart.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/star.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/star.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/star.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/star.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/system-lock-screen.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/system-lock-screen.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/system-lock-screen.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/system-lock-screen.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/zoom-in.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/zoom-in.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/zoom-in.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/zoom-in.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/zoom-out.png b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/zoom-out.png similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/resources/zoom-out.png rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/resources/zoom-out.png diff --git a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkFloatingImageToUltrasoundRegistrationFilter.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkFloatingImageToUltrasoundRegistrationFilter.cpp new file mode 100644 index 0000000000..e765dee947 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkFloatingImageToUltrasoundRegistrationFilter.cpp @@ -0,0 +1,192 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkFloatingImageToUltrasoundRegistrationFilter.h" +#include +#include + + +mitk::FloatingImageToUltrasoundRegistrationFilter::FloatingImageToUltrasoundRegistrationFilter() +: mitk::NavigationDataPassThroughFilter(), + m_Segmentation(nullptr), + m_TransformMarkerCSToSensorCS(mitk::AffineTransform3D::New()), + m_TransformMarkerCSToFloatingImageCS(mitk::AffineTransform3D::New()), + m_TransformUSimageCSToTrackingCS(mitk::AffineTransform3D::New()), + m_TransformCTimageIndexToWorld(mitk::AffineTransform3D::New()), + m_TrackedUltrasoundActive(false) +{ + m_SurfaceGeometry = mitk::Geometry3D::New(); + m_PointSet = nullptr; + m_CTimage = mitk::Image::New(); +} + +mitk::FloatingImageToUltrasoundRegistrationFilter::~FloatingImageToUltrasoundRegistrationFilter() +{ +} + +void mitk::FloatingImageToUltrasoundRegistrationFilter::InitializeTransformationMarkerCSToSensorCS( bool useNdiTracker) +{ + //The following calculations are related to the 3mm | 15mm fiducial configuration + + m_TransformMarkerCSToSensorCS = mitk::AffineTransform3D::New(); + + if (useNdiTracker) // Use the NDI disc tracker for performing the CT-to-US registration: + { + MITK_INFO << "Use NDI disc tracker for performing the CT-to-US-registration"; + mitk::Vector3D translationNDI; + translationNDI[0] = 15.000; + translationNDI[1] = 8.000; + translationNDI[2] = -2.500; // use -2.500 instead of 0.000 for the z translation if working with v2 of the + // sensor adapter. + + m_TransformMarkerCSToSensorCS->SetOffset(translationNDI); + + // Quaternion (x, y, z, r) --> n = (0,0,1) --> q(0,0,sin(90°),cos(90°)) + mitk::Quaternion qNDI(0, 0, 1, 0); // corresponding to a rotation of 180° around the normal z-axis. + // .transpose() is needed for changing the rows and the columns of the returned rotation_matrix_transpose + vnl_matrix_fixed vnl_rotation = qNDI.rotation_matrix_transpose().transpose(); // :-) + mitk::Matrix3D rotationMatrix; + + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + rotationMatrix[i][j] = vnl_rotation[i][j]; + } + } + + m_TransformMarkerCSToSensorCS->SetMatrix(rotationMatrix); + } + else // Use the polhemus RX2 tracker for performing the CT-to-US registration: + { + MITK_INFO << "Use Polhemus RX2 tracker for performing the CT-to-US-registration"; + mitk::Vector3D translationPolhemus; + translationPolhemus[0] = -18.175; + translationPolhemus[1] = 15.000; + translationPolhemus[2] = 10.501; // considering a distance from the base plate of 0.315 inch and not 0.313 inch + // use 10.501 instead of 8.001 for the z translation if working with v2 of the + // sensor adapter. + + m_TransformMarkerCSToSensorCS->SetOffset(translationPolhemus); + + // Quaternion (x, y, z, r) --> n = (1,0,0) --> q(sin(90°),0,0,cos(90°)) + mitk::Quaternion q1(1, 0, 0, 0); // corresponding to a rotation of 180° around the normal x-axis. + // .transpose() is needed for changing the rows and the columns of the returned rotation_matrix_transpose + vnl_matrix_fixed vnl_rotation = q1.rotation_matrix_transpose().transpose(); // :-) + mitk::Matrix3D rotationMatrix; + + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + rotationMatrix[i][j] = vnl_rotation[i][j]; + } + } + + m_TransformMarkerCSToSensorCS->SetMatrix(rotationMatrix); + } + //The transformation from the sensor-CS to the marker-CS is calculated now. +} + +void mitk::FloatingImageToUltrasoundRegistrationFilter::SetSegmentation(mitk::DataNode::Pointer segmentationNode, mitk::Image::Pointer ctimage) +{ + m_Segmentation = segmentationNode; + m_TransformCTimageIndexToWorld = m_Segmentation->GetData()->GetGeometry()->GetIndexToWorldTransform(); + m_CTimage = ctimage; +} + +void mitk::FloatingImageToUltrasoundRegistrationFilter::SetSurface(mitk::DataNode::Pointer surfaceNode) +{ + m_Surface = surfaceNode; + m_SurfaceGeometry = m_Surface->GetData()->GetGeometry(); +} + +void mitk::FloatingImageToUltrasoundRegistrationFilter::SetPointSet(mitk::DataNode::Pointer pointSetNode) +{ + m_PointSet = pointSetNode; +} + +void mitk::FloatingImageToUltrasoundRegistrationFilter::SetTransformMarkerCSToFloatingImageCS(mitk::AffineTransform3D::Pointer transform) +{ + m_TransformMarkerCSToFloatingImageCS = transform; +} + +void mitk::FloatingImageToUltrasoundRegistrationFilter::SetTransformUSimageCSToTrackingCS(mitk::AffineTransform3D::Pointer transform) +{ + m_TransformUSimageCSToTrackingCS = transform; +} + +void mitk::FloatingImageToUltrasoundRegistrationFilter::GenerateData() +{ + Superclass::GenerateData(); + + if (m_TrackedUltrasoundActive) + { + MITK_WARN << "The CT-to-US-registration is not supported by tracked ultrasound, yet."; + return; + } + + //IMPORTANT --- Hard coded --- First device = EM-Sensor | eventually second device = needle + mitk::NavigationData::Pointer transformSensorCSToTracking = this->GetOutput(0); + + // cancel, if the EM-sensor is currently not being tracked + if (!transformSensorCSToTracking->IsDataValid()) + { + return; + } + + //We start the transformation with a new transform: + mitk::AffineTransform3D::Pointer totalTransformation = mitk::AffineTransform3D::New(); + totalTransformation->SetIdentity(); + //Compose it with the inverse transform of marker-CS to floating image-CS: + totalTransformation->Compose(this->GetInverseTransform(m_TransformMarkerCSToFloatingImageCS)); + //Compose this with the inverse transform of EM-sensor-CS to marker-CS: + totalTransformation->Compose(m_TransformMarkerCSToSensorCS); + //Compose this with the transform of the sensor-CS to Tracking-CS: + totalTransformation->Compose(transformSensorCSToTracking->GetAffineTransform3D()); + //Compose this with the inverse transform of USimage-CS to tracking-CS: + totalTransformation->Modified(); + + //Finally, set the total transformation (from floatingImage-CS to US-image-CS + // to the selected floatingImageSurface: + + //m_Segmentation->GetData()->GetGeometry()->SetIndexToWorldTransform(totalTransformation); + //m_Segmentation->Modified(); + + //m_CTimage->GetGeometry()->SetIndexToWorldTransform(totalTransformation); + //m_CTimage->Modified(); + + m_Surface->GetData()->GetGeometry()->SetIndexToWorldTransform(totalTransformation); + m_Surface->Modified(); + + m_PointSet->GetData()->GetGeometry()->SetIndexToWorldTransform(totalTransformation); + m_PointSet->Modified(); +} + +mitk::AffineTransform3D::Pointer mitk::FloatingImageToUltrasoundRegistrationFilter::GetInverseTransform(mitk::AffineTransform3D::Pointer transform) +{ + mitk::AffineTransform3D::Pointer inverseTransform = mitk::AffineTransform3D::New(); + mitk::AffineTransform3D::Pointer inverse = dynamic_cast(transform->GetInverseTransform().GetPointer()); + + //itk::SmartPointer> inverse = dynamic_cast*> (transform->GetInverseTransform().GetPointer()); //itkScalableAffineTransform_hxx + + if (inverse.IsNull()) + { + MITK_WARN << "Could not get inverse transform of mitk::AffineTransform3D. Returning nullptr"; + return nullptr; + } + + inverseTransform->SetOffset(inverse->GetOffset()); + inverseTransform->SetMatrix(inverse->GetMatrix()); + + return inverseTransform; +} diff --git a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkFloatingImageToUltrasoundRegistrationFilter.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkFloatingImageToUltrasoundRegistrationFilter.h new file mode 100644 index 0000000000..e2cc461cc1 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkFloatingImageToUltrasoundRegistrationFilter.h @@ -0,0 +1,74 @@ +/*=================================================================== + +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 MITKFLOATINGIMAGETOULTRASOUNDREGISTRATIONFILTER_H_HEADER_INCLUDED_ +#define MITKFLOATINGIMAGETOULTRASOUNDREGISTRATIONFILTER_H_HEADER_INCLUDED_ + +#include +#include + +namespace mitk +{ + /**Documentation + * \brief This filter transforms a given floating image into the ultrasound coordinate system. + * + * + * \ingroup US + */ + class FloatingImageToUltrasoundRegistrationFilter : public NavigationDataPassThroughFilter + { + public: + mitkClassMacro(FloatingImageToUltrasoundRegistrationFilter, NavigationDataPassThroughFilter); + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + void InitializeTransformationMarkerCSToSensorCS( bool useNdiTracker = false ); + + void SetSegmentation(mitk::DataNode::Pointer segmentationNode, mitk::Image::Pointer ctimage); + void SetSurface(mitk::DataNode::Pointer surfaceNode); + void SetPointSet(mitk::DataNode::Pointer pointSetNode); + void SetTransformMarkerCSToFloatingImageCS( mitk::AffineTransform3D::Pointer transform ); + void SetTransformUSimageCSToTrackingCS(mitk::AffineTransform3D::Pointer transform); + + protected: + FloatingImageToUltrasoundRegistrationFilter(); + ~FloatingImageToUltrasoundRegistrationFilter() override; + + /**Documentation + * \brief filter execute method + * + * + */ + void GenerateData() override; + + mitk::AffineTransform3D::Pointer GetInverseTransform(mitk::AffineTransform3D::Pointer transform); + + private: + mitk::DataNode::Pointer m_Segmentation; + mitk::DataNode::Pointer m_Surface; + mitk::DataNode::Pointer m_PointSet; + mitk::Image::Pointer m_CTimage; + mitk::AffineTransform3D::Pointer m_TransformMarkerCSToSensorCS; + mitk::AffineTransform3D::Pointer m_TransformMarkerCSToFloatingImageCS; + mitk::AffineTransform3D::Pointer m_TransformUSimageCSToTrackingCS; + mitk::AffineTransform3D::Pointer m_TransformCTimageIndexToWorld; + mitk::BaseGeometry::Pointer m_SurfaceGeometry; + bool m_TrackedUltrasoundActive; + + }; +} // namespace mitk +#endif // MITKFLOATINGIMAGETOULTRASOUNDREGISTRATIONFILTER_H_HEADER_INCLUDED_ diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Filter/mitkUSNavigationTargetIntersectionFilter.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkUSNavigationTargetIntersectionFilter.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Filter/mitkUSNavigationTargetIntersectionFilter.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkUSNavigationTargetIntersectionFilter.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Filter/mitkUSNavigationTargetIntersectionFilter.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkUSNavigationTargetIntersectionFilter.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Filter/mitkUSNavigationTargetIntersectionFilter.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkUSNavigationTargetIntersectionFilter.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Filter/mitkUSNavigationTargetOcclusionFilter.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkUSNavigationTargetOcclusionFilter.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Filter/mitkUSNavigationTargetOcclusionFilter.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkUSNavigationTargetOcclusionFilter.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Filter/mitkUSNavigationTargetOcclusionFilter.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkUSNavigationTargetOcclusionFilter.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Filter/mitkUSNavigationTargetOcclusionFilter.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkUSNavigationTargetOcclusionFilter.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Filter/mitkUSNavigationTargetUpdateFilter.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkUSNavigationTargetUpdateFilter.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Filter/mitkUSNavigationTargetUpdateFilter.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkUSNavigationTargetUpdateFilter.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Filter/mitkUSNavigationTargetUpdateFilter.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkUSNavigationTargetUpdateFilter.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Filter/mitkUSNavigationTargetUpdateFilter.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Filter/mitkUSNavigationTargetUpdateFilter.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationCombinedModalityPersistence.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationCombinedModalityPersistence.cpp similarity index 95% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationCombinedModalityPersistence.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationCombinedModalityPersistence.cpp index cd2a4d0017..44f8bad907 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationCombinedModalityPersistence.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationCombinedModalityPersistence.cpp @@ -1,213 +1,213 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkUSNavigationCombinedModalityPersistence.h" #include "mitkUSCombinedModality.h" // Microservices #include #include #include #include // Qt #include #include #include #include #include "internal/org_mbi_gui_qt_usnavigation_Activator.h" mitk::USNavigationCombinedModalityPersistence::USNavigationCombinedModalityPersistence() { us::ModuleContext* context = us::GetModuleContext(); this->LoadStoredDevices(); // to be notified about every register and unregister of an USDevice std::string filterExcludeCombinedModalities = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice)(!(" + mitk::USDevice::GetPropertyKeys().US_PROPKEY_CLASS + "=" + mitk::USCombinedModality::DeviceClassIdentifier + ")))"; context->AddServiceListener(this, &mitk::USNavigationCombinedModalityPersistence::OnServiceEvent, filterExcludeCombinedModalities); // to be notified about every register and unregister of an NavigationDataSource context->AddServiceListener(this, &mitk::USNavigationCombinedModalityPersistence::OnServiceEvent, "(" + us::ServiceConstants::OBJECTCLASS() + "=" + us_service_interface_iid() + ")"); } mitk::USNavigationCombinedModalityPersistence::~USNavigationCombinedModalityPersistence() { //this->StoreCurrentDevices(); //disabled because persistence is buggy } void mitk::USNavigationCombinedModalityPersistence::OnServiceEvent(const us::ServiceEvent event) { if ( event.GetType() == event.REGISTERED ) { //this->LoadStoredDevices(); //disabled because persistence is buggy } } void mitk::USNavigationCombinedModalityPersistence::StoreCurrentDevices() { QList devices; us::ModuleContext* context = us::GetModuleContext(); // get all combined modality from the service registry std::string filterOnlyCombinedModalities = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice)(" + mitk::USDevice::GetPropertyKeys().US_PROPKEY_CLASS + "=" + mitk::USCombinedModality::DeviceClassIdentifier + "))"; std::vector > services = context->GetServiceReferences(filterOnlyCombinedModalities); for ( std::vector >::iterator it = services.begin(); it != services.end(); ++it ) { QStringList deviceStrings; mitk::USCombinedModality::Pointer currentDevice = dynamic_cast(context->GetService(*it)); if ( currentDevice.IsNotNull() ) { // save manufacturer and model strig of the combined modality - deviceStrings.push_back(QString::fromStdString(currentDevice->GetManufacturer())); - deviceStrings.push_back(QString::fromStdString(currentDevice->GetName())); + deviceStrings.push_back(QString::fromStdString(currentDevice->GetUltrasoundDevice()->GetManufacturer())); + deviceStrings.push_back(QString::fromStdString(currentDevice->GetUltrasoundDevice()->GetName())); // save name of the navigation data source mitk::NavigationDataSource::Pointer navigationDataSource = currentDevice->GetNavigationDataSource(); if ( currentDevice.IsNull() ) { continue; } deviceStrings.push_back(QString::fromStdString(navigationDataSource->GetName())); // save manufacturer, model and comment of the ultrasound device mitk::USDevice::Pointer ultrasoundDevice = currentDevice->GetUltrasoundDevice(); if ( ultrasoundDevice.IsNull() ) { continue; } deviceStrings.push_back(QString::fromStdString(ultrasoundDevice->GetManufacturer())); deviceStrings.push_back(QString::fromStdString(ultrasoundDevice->GetName())); deviceStrings.push_back(QString::fromStdString(ultrasoundDevice->GetComment())); // save calibration of the combined modality deviceStrings.push_back(QString::fromStdString(currentDevice->SerializeCalibration())); } devices.push_back(deviceStrings); } // store everything in QSettings QSettings settings; settings.setValue("combined-modalities", devices); } void mitk::USNavigationCombinedModalityPersistence::LoadStoredDevices() { // load everything from QSettings QSettings settings; QList devices = settings.value("combined-modalities").value< QList >(); for ( QList::iterator it = devices.begin(); it != devices.end(); ++it ) { // get the saved strings for the combined modality (there must be at least // the seven strings, which where saved before) QStringList stringList = it->toStringList(); // test if the combined modality wasn't restored before if (stringList.size() >= 7 && this->GetCombinedModality(stringList.at(0).toStdString(), stringList.at(1).toStdString()).IsNull()) { // try to get matching navigation data source and ultrasound device mitk::NavigationDataSource::Pointer navigationDataSource = this->GetNavigationDataSource(stringList.at(2).toStdString()); mitk::USDevice::Pointer usDevice = this->GetUSDevice(stringList.at(3).toStdString(), stringList.at(4).toStdString(), stringList.at(5).toStdString()); // create the combined modality if matching navigation data source and // ultrasound device werde found if ( navigationDataSource.IsNotNull() && usDevice.IsNotNull() ) { - mitk::USCombinedModality::Pointer combinedModality = mitk::USCombinedModality::New(usDevice, navigationDataSource, stringList.at(0).toStdString(), stringList.at(1).toStdString()); + mitk::USCombinedModality::Pointer combinedModality = mitk::USCombinedModality::New(usDevice, navigationDataSource, false); combinedModality->DeserializeCalibration(stringList.at(6).toStdString()); - combinedModality->Initialize(); + combinedModality->GetUltrasoundDevice()->Initialize(); } } } } mitk::USCombinedModality::Pointer mitk::USNavigationCombinedModalityPersistence::GetCombinedModality(std::string manufacturer, std::string model) { us::ModuleContext* context = us::GetModuleContext(); std::string filterOnlyCombinedModalities = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice)(" + mitk::USDevice::GetPropertyKeys().US_PROPKEY_CLASS + "=" + mitk::USCombinedModality::DeviceClassIdentifier + "))"; std::vector > services = context->GetServiceReferences(filterOnlyCombinedModalities); for ( std::vector >::iterator it = services.begin(); it != services.end(); ++it ) { mitk::USCombinedModality::Pointer currentDevice = dynamic_cast(context->GetService(*it)); if ( currentDevice.IsNotNull() ) { - if ( currentDevice->GetManufacturer() == manufacturer && currentDevice->GetName() == model ) + if ( currentDevice->GetUltrasoundDevice()->GetManufacturer() == manufacturer && currentDevice->GetUltrasoundDevice()->GetName() == model ) { return currentDevice; } } } return 0; } mitk::USDevice::Pointer mitk::USNavigationCombinedModalityPersistence::GetUSDevice(std::string manufacturer, std::string model, std::string comment) { us::ModuleContext* context = us::GetModuleContext(); std::string filterExcludeCombinedModalities = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice)(!(" + mitk::USDevice::GetPropertyKeys().US_PROPKEY_CLASS + "=" + mitk::USCombinedModality::DeviceClassIdentifier + ")))"; std::vector > services = context->GetServiceReferences(filterExcludeCombinedModalities); for ( std::vector >::iterator it = services.begin(); it != services.end(); ++it ) { mitk::USDevice::Pointer currentDevice = dynamic_cast(context->GetService(*it)); if ( currentDevice.IsNotNull() ) { if ( currentDevice->GetManufacturer() == manufacturer && currentDevice->GetName() == model && currentDevice->GetComment() == comment ) { return currentDevice; } } } return 0; } mitk::NavigationDataSource::Pointer mitk::USNavigationCombinedModalityPersistence::GetNavigationDataSource(std::string name) { us::ModuleContext* context = us::GetModuleContext(); std::vector > services = context->GetServiceReferences(); for ( std::vector >::iterator it = services.begin(); it != services.end(); ++it ) { mitk::NavigationDataSource::Pointer currentDevice = dynamic_cast(context->GetService(*it)); if ( currentDevice.IsNotNull() ) { if ( currentDevice->GetName() == name ) { return currentDevice; } } } return 0; } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationCombinedModalityPersistence.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationCombinedModalityPersistence.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationCombinedModalityPersistence.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationCombinedModalityPersistence.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationExperimentLogging.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationExperimentLogging.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationExperimentLogging.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationExperimentLogging.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationExperimentLogging.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationExperimentLogging.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationExperimentLogging.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationExperimentLogging.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationLoggingBackend.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationLoggingBackend.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationLoggingBackend.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationLoggingBackend.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationLoggingBackend.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationLoggingBackend.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationLoggingBackend.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationLoggingBackend.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationStepTimer.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationStepTimer.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationStepTimer.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationStepTimer.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationStepTimer.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationStepTimer.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/IO/mitkUSNavigationStepTimer.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationStepTimer.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Interactors/mitkUSPointMarkInteractor.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Interactors/mitkUSPointMarkInteractor.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Interactors/mitkUSPointMarkInteractor.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Interactors/mitkUSPointMarkInteractor.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Interactors/mitkUSPointMarkInteractor.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Interactors/mitkUSPointMarkInteractor.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Interactors/mitkUSPointMarkInteractor.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Interactors/mitkUSPointMarkInteractor.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Interactors/mitkUSZonesInteractor.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Interactors/mitkUSZonesInteractor.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Interactors/mitkUSZonesInteractor.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Interactors/mitkUSZonesInteractor.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Interactors/mitkUSZonesInteractor.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Interactors/mitkUSZonesInteractor.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Interactors/mitkUSZonesInteractor.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Interactors/mitkUSZonesInteractor.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.cpp similarity index 93% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.cpp index 774f3a2594..e7afbbd4bf 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.cpp @@ -1,208 +1,209 @@ /*=================================================================== 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; + MITK_INFO << "Combined modality set to NULL: " << m_CombinedModality.IsNull(); 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) +itk::SmartPointer QmitkUSAbstractNavigationStep::GetCombinedModality(bool throwNull) { if ( throwNull && m_CombinedModality.IsNull() ) { - MITK_ERROR << "Combined modality is not set yet for this widget."; + MITK_INFO << "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.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.h similarity index 96% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.h index f61a605670..02d663a7c9 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.h +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/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" +#include "mitkAbstractUltrasoundTrackerDevice.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); + 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; + itk::SmartPointer m_CombinedModality; NavigationStepState m_NavigationStepState; }; #endif // QMITKUSABSTRACTNAVIGATIONSTEP_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.ui similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.ui diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp similarity index 84% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp index 00ab7836c7..6cf3cb256b 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp @@ -1,428 +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::USCombinedModality::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->GetDeviceState() >= mitk::USCombinedModality::State_Connected); - ui->combinedModalityActivateButton->setEnabled(combinedModality->GetDeviceState() < mitk::USCombinedModality::State_Activated); + 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"; + MITK_WARN << "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->GetIsConnected()) { combinedModality->Connect(); } - if (!combinedModality->GetIsActive()) { combinedModality->Activate(); } + 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->GetIsActive()) { combinedModality->Deactivate(); } - if (combinedModality->GetIsConnected()) { combinedModality->Disconnect(); } + 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->GetDeviceState() < mitk::USDevice::State_Connected) { combinedModality->Connect(); } - if (combinedModality->GetDeviceState() < mitk::USDevice::State_Activated) { combinedModality->Activate(); } + 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::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(); + 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->GetManufacturer() + ": " + combinedModality->GetName() - + " (" + combinedModality->GetComment() + ")").c_str()); + 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.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h similarity index 95% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h index 66d9f22848..2df8b2dd3a 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/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; + 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/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.ui similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.ui diff --git a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.cpp new file mode 100644 index 0000000000..835864f7e0 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.cpp @@ -0,0 +1,2018 @@ +/*=================================================================== + +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 "QmitkUSNavigationStepCtUsRegistration.h" +#include "ui_QmitkUSNavigationStepCtUsRegistration.h" + +#include + +#include "mitkNodeDisplacementFilter.h" +#include "../Filter/mitkFloatingImageToUltrasoundRegistrationFilter.h" +#include "../QmitkUSNavigationMarkerPlacement.h" + + + +#include +#include +#include +#include "mitkProperties.h" +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +static const int NUMBER_FIDUCIALS_NEEDED = 8; + +QmitkUSNavigationStepCtUsRegistration::QmitkUSNavigationStepCtUsRegistration(QWidget *parent) : + QmitkUSAbstractNavigationStep(parent), + ui(new Ui::QmitkUSNavigationStepCtUsRegistration), + m_PerformingGroundTruthProtocolEvaluation(false), + m_FloatingImageToUltrasoundRegistrationFilter(nullptr), + m_FreezeCombinedModality(false) +{ + this->UnsetFloatingImageGeometry(); + this->DefineDataStorageImageFilter(); + this->CreateQtPartControl(this); +} + + +QmitkUSNavigationStepCtUsRegistration::~QmitkUSNavigationStepCtUsRegistration() +{ + delete ui; +} + +bool QmitkUSNavigationStepCtUsRegistration::OnStartStep() +{ + MITK_INFO << "OnStartStep()"; + return true; +} + +bool QmitkUSNavigationStepCtUsRegistration::OnStopStep() +{ + MITK_INFO << "OnStopStep()"; + return true; +} + +bool QmitkUSNavigationStepCtUsRegistration::OnFinishStep() +{ + MITK_INFO << "OnFinishStep()"; + return true; +} + +bool QmitkUSNavigationStepCtUsRegistration::OnActivateStep() +{ + MITK_INFO << "OnActivateStep()"; + ui->floatingImageComboBox->SetDataStorage(this->GetDataStorage()); + ui->ctImagesToChooseComboBox->SetDataStorage(this->GetDataStorage()); + ui->segmentationComboBox->SetDataStorage(this->GetDataStorage()); + ui->selectedSurfaceComboBox->SetDataStorage(this->GetDataStorage()); + ui->pointSetComboBox->SetDataStorage(this->GetDataStorage()); + m_FloatingImageToUltrasoundRegistrationFilter = + mitk::FloatingImageToUltrasoundRegistrationFilter::New(); + return true; +} + +bool QmitkUSNavigationStepCtUsRegistration::OnDeactivateStep() +{ + MITK_INFO << "OnDeactivateStep()"; + return true; +} + +void QmitkUSNavigationStepCtUsRegistration::OnUpdate() +{ + if (m_NavigationDataSource.IsNull()) { return; } + + m_NavigationDataSource->Update(); + m_FloatingImageToUltrasoundRegistrationFilter->Update(); +} + +void QmitkUSNavigationStepCtUsRegistration::OnSettingsChanged(const itk::SmartPointer settingsNode) +{ + Q_UNUSED(settingsNode); +} + +QString QmitkUSNavigationStepCtUsRegistration::GetTitle() +{ + return "CT-to-US registration"; +} + +QmitkUSAbstractNavigationStep::FilterVector QmitkUSNavigationStepCtUsRegistration::GetFilter() +{ + return FilterVector(); +} + +void QmitkUSNavigationStepCtUsRegistration::OnSetCombinedModality() +{ + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(false); + if (combinedModality.IsNotNull()) + { + m_NavigationDataSource = combinedModality->GetNavigationDataSource(); + } + +} + +void QmitkUSNavigationStepCtUsRegistration::UnsetFloatingImageGeometry() +{ + m_ImageDimension[0] = 0; + m_ImageDimension[1] = 0; + m_ImageDimension[2] = 0; + + m_ImageSpacing[0] = 1; + m_ImageSpacing[1] = 1; + m_ImageSpacing[2] = 1; +} + +void QmitkUSNavigationStepCtUsRegistration::SetFloatingImageGeometryInformation(mitk::Image * image) +{ + m_ImageDimension[0] = image->GetDimension(0); + m_ImageDimension[1] = image->GetDimension(1); + m_ImageDimension[2] = image->GetDimension(2); + + m_ImageSpacing[0] = image->GetGeometry()->GetSpacing()[0]; + m_ImageSpacing[1] = image->GetGeometry()->GetSpacing()[1]; + m_ImageSpacing[2] = image->GetGeometry()->GetSpacing()[2]; +} + +double QmitkUSNavigationStepCtUsRegistration::GetVoxelVolume() +{ + if (m_FloatingImage.IsNull()) + { + return 0.0; + } + + MITK_INFO << "ImageSpacing = " << m_ImageSpacing; + return m_ImageSpacing[0] * m_ImageSpacing[1] * m_ImageSpacing[2]; +} + +double QmitkUSNavigationStepCtUsRegistration::GetFiducialVolume(double radius) +{ + return 1.333333333 * 3.141592 * (radius * radius * radius); +} + +bool QmitkUSNavigationStepCtUsRegistration::FilterFloatingImage() +{ + if (m_FloatingImage.IsNull()) + { + return false; + } + + ImageType::Pointer itkImage1 = ImageType::New(); + mitk::CastToItkImage(m_FloatingImage, itkImage1); + + this->InitializeImageFilters(); + + m_ThresholdFilter->SetInput(itkImage1); + m_LaplacianFilter1->SetInput(m_ThresholdFilter->GetOutput()); + m_LaplacianFilter2->SetInput(m_LaplacianFilter1->GetOutput()); + m_BinaryThresholdFilter->SetInput(m_LaplacianFilter2->GetOutput()); + m_HoleFillingFilter->SetInput(m_BinaryThresholdFilter->GetOutput()); + m_BinaryImageToShapeLabelMapFilter->SetInput(m_HoleFillingFilter->GetOutput()); + m_BinaryImageToShapeLabelMapFilter->Update(); + + ImageType::Pointer binaryImage = ImageType::New(); + binaryImage = m_HoleFillingFilter->GetOutput(); + + this->EliminateTooSmallLabeledObjects(binaryImage); + //mitk::CastToMitkImage(binaryImage, m_FloatingImage); + return true; +} + +void QmitkUSNavigationStepCtUsRegistration::InitializeImageFilters() +{ + //Initialize threshold filters + m_ThresholdFilter = itk::ThresholdImageFilter::New(); + m_ThresholdFilter->SetOutsideValue(0); + m_ThresholdFilter->SetLower(500); + m_ThresholdFilter->SetUpper(3200); + + //Initialize binary threshold filter 1 + m_BinaryThresholdFilter = BinaryThresholdImageFilterType::New(); + m_BinaryThresholdFilter->SetOutsideValue(0); + m_BinaryThresholdFilter->SetInsideValue(1); + m_BinaryThresholdFilter->SetLowerThreshold(350); + m_BinaryThresholdFilter->SetUpperThreshold(10000); + + //Initialize laplacian recursive gaussian image filter + m_LaplacianFilter1 = LaplacianRecursiveGaussianImageFilterType::New(); + m_LaplacianFilter2 = LaplacianRecursiveGaussianImageFilterType::New(); + + //Initialize binary hole filling filter + m_HoleFillingFilter = VotingBinaryIterativeHoleFillingImageFilterType::New(); + VotingBinaryIterativeHoleFillingImageFilterType::InputSizeType radius; + radius.Fill(1); + m_HoleFillingFilter->SetRadius(radius); + m_HoleFillingFilter->SetBackgroundValue(0); + m_HoleFillingFilter->SetForegroundValue(1); + m_HoleFillingFilter->SetMaximumNumberOfIterations(5); + + //Initialize binary image to shape label map filter + m_BinaryImageToShapeLabelMapFilter = BinaryImageToShapeLabelMapFilterType::New(); + m_BinaryImageToShapeLabelMapFilter->SetInputForegroundValue(1); +} + +double QmitkUSNavigationStepCtUsRegistration::GetCharacteristicDistanceAWithUpperMargin() +{ + switch (ui->fiducialMarkerConfigurationComboBox->currentIndex()) + { + // case 0 is equal to fiducial marker configuration A (10mm distance) + case 0: + return 12.07; + + // case 1 is equal to fiducial marker configuration B (15mm distance) + case 1: + return 18.105; + + // case 2 is equal to fiducial marker configuration C (20mm distance) + case 2: + return 24.14; + } + return 0.0; +} + +double QmitkUSNavigationStepCtUsRegistration::GetCharacteristicDistanceBWithLowerMargin() +{ + switch (ui->fiducialMarkerConfigurationComboBox->currentIndex()) + { + // case 0 is equal to fiducial marker configuration A (10mm distance) + case 0: + return 12.07; + + // case 1 is equal to fiducial marker configuration B (15mm distance) + case 1: + return 18.105; + + // case 2 is equal to fiducial marker configuration C (20mm distance) + case 2: + return 24.14; + } + return 0.0; +} + +double QmitkUSNavigationStepCtUsRegistration::GetCharacteristicDistanceBWithUpperMargin() +{ + switch (ui->fiducialMarkerConfigurationComboBox->currentIndex()) + { + // case 0 is equal to fiducial marker configuration A (10mm distance) + case 0: + return 15.73; + + // case 1 is equal to fiducial marker configuration B (15mm distance) + case 1: + return 23.595; + + // case 2 is equal to fiducial marker configuration C (20mm distance) + case 2: + return 31.46; + } + return 0.0; +} + +double QmitkUSNavigationStepCtUsRegistration::GetMinimalFiducialConfigurationDistance() +{ + switch (ui->fiducialMarkerConfigurationComboBox->currentIndex()) + { + // case 0 is equal to fiducial marker configuration A (10mm distance) + case 0: + return 10.0; + + // case 1 is equal to fiducial marker configuration B (15mm distance) + case 1: + return 15.0; + + // case 2 is equal to fiducial marker configuration C (20mm distance) + case 2: + return 20.0; + } + return 0.0; +} + +void QmitkUSNavigationStepCtUsRegistration::CreateMarkerModelCoordinateSystemPointSet() +{ + if (m_MarkerModelCoordinateSystemPointSet.IsNull()) + { + m_MarkerModelCoordinateSystemPointSet = mitk::PointSet::New(); + } + else + { + m_MarkerModelCoordinateSystemPointSet->Clear(); + } + + mitk::Point3D fiducial1; + mitk::Point3D fiducial2; + mitk::Point3D fiducial3; + mitk::Point3D fiducial4; + mitk::Point3D fiducial5; + mitk::Point3D fiducial6; + mitk::Point3D fiducial7; + mitk::Point3D fiducial8; + + + + switch (ui->fiducialMarkerConfigurationComboBox->currentIndex()) + { + // case 0 is equal to fiducial marker configuration A (10mm distance) + case 0: + fiducial1[0] = 0; + fiducial1[1] = 0; + fiducial1[2] = 0; + + fiducial2[0] = 0; + fiducial2[1] = 10; + fiducial2[2] = 0; + + fiducial3[0] = 10; + fiducial3[1] = 0; + fiducial3[2] = 0; + + fiducial4[0] = 20; + fiducial4[1] = 20; + fiducial4[2] = 0; + + fiducial5[0] = 0; + fiducial5[1] = 20; + fiducial5[2] = 10; + + fiducial6[0] = 10; + fiducial6[1] = 20; + fiducial6[2] = 10; + + fiducial7[0] = 20; + fiducial7[1] = 10; + fiducial7[2] = 10; + + fiducial8[0] = 20; + fiducial8[1] = 0; + fiducial8[2] = 10; + break; + // case 1 is equal to fiducial marker configuration B (15mm distance) + case 1: + fiducial1[0] = 0; + fiducial1[1] = 0; + fiducial1[2] = 0; + + fiducial2[0] = 0; + fiducial2[1] = 15; + fiducial2[2] = 0; + + fiducial3[0] = 15; + fiducial3[1] = 0; + fiducial3[2] = 0; + + fiducial4[0] = 30; + fiducial4[1] = 30; + fiducial4[2] = 0; + + fiducial5[0] = 0; + fiducial5[1] = 30; + fiducial5[2] = 15; + + fiducial6[0] = 15; + fiducial6[1] = 30; + fiducial6[2] = 15; + + fiducial7[0] = 30; + fiducial7[1] = 15; + fiducial7[2] = 15; + + fiducial8[0] = 30; + fiducial8[1] = 0; + fiducial8[2] = 15; + break; + // case 2 is equal to fiducial marker configuration C (20mm distance) + case 2: + fiducial1[0] = 0; + fiducial1[1] = 0; + fiducial1[2] = 0; + + fiducial2[0] = 0; + fiducial2[1] = 20; + fiducial2[2] = 0; + + fiducial3[0] = 20; + fiducial3[1] = 0; + fiducial3[2] = 0; + + fiducial4[0] = 40; + fiducial4[1] = 40; + fiducial4[2] = 0; + + fiducial5[0] = 0; + fiducial5[1] = 40; + fiducial5[2] = 20; + + fiducial6[0] = 20; + fiducial6[1] = 40; + fiducial6[2] = 20; + + fiducial7[0] = 40; + fiducial7[1] = 20; + fiducial7[2] = 20; + + fiducial8[0] = 40; + fiducial8[1] = 0; + fiducial8[2] = 20; + break; + } + + m_MarkerModelCoordinateSystemPointSet->InsertPoint(0, fiducial1); + m_MarkerModelCoordinateSystemPointSet->InsertPoint(1, fiducial2); + m_MarkerModelCoordinateSystemPointSet->InsertPoint(2, fiducial3); + m_MarkerModelCoordinateSystemPointSet->InsertPoint(3, fiducial4); + m_MarkerModelCoordinateSystemPointSet->InsertPoint(4, fiducial5); + m_MarkerModelCoordinateSystemPointSet->InsertPoint(5, fiducial6); + m_MarkerModelCoordinateSystemPointSet->InsertPoint(6, fiducial7); + m_MarkerModelCoordinateSystemPointSet->InsertPoint(7, fiducial8); + + /*mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Marker Model Coordinate System Point Set"); + if (node == nullptr) + { + node = mitk::DataNode::New(); + node->SetName("Marker Model Coordinate System Point Set"); + node->SetData(m_MarkerModelCoordinateSystemPointSet); + this->GetDataStorage()->Add(node); + } + else + { + node->SetData(m_MarkerModelCoordinateSystemPointSet); + this->GetDataStorage()->Modified(); + }*/ +} + +void QmitkUSNavigationStepCtUsRegistration::InitializePointsToTransformForGroundTruthProtocol() +{ + + m_PointsToTransformGroundTruthProtocol.clear(); + + mitk::Point3D point0mm; + mitk::Point3D point20mm; + mitk::Point3D point40mm; + mitk::Point3D point60mm; + mitk::Point3D point80mm; + mitk::Point3D point100mm; + + point0mm[0] = 0.0; + point0mm[1] = 0.0; + point0mm[2] = 0.0; + + point20mm[0] = 0.0; + point20mm[1] = 0.0; + point20mm[2] = 0.0; + + point40mm[0] = 0.0; + point40mm[1] = 0.0; + point40mm[2] = 0.0; + + point60mm[0] = 0.0; + point60mm[1] = 0.0; + point60mm[2] = 0.0; + + point80mm[0] = 0.0; + point80mm[1] = 0.0; + point80mm[2] = 0.0; + + point100mm[0] = 0.0; + point100mm[1] = 0.0; + point100mm[2] = 0.0; + + m_PointsToTransformGroundTruthProtocol.insert(std::pair(0, point0mm)); + m_PointsToTransformGroundTruthProtocol.insert(std::pair(20, point20mm)); + m_PointsToTransformGroundTruthProtocol.insert(std::pair(40, point40mm)); + m_PointsToTransformGroundTruthProtocol.insert(std::pair(60, point60mm)); + m_PointsToTransformGroundTruthProtocol.insert(std::pair(80, point80mm)); + m_PointsToTransformGroundTruthProtocol.insert(std::pair(100, point100mm)); +} + +void QmitkUSNavigationStepCtUsRegistration::CreatePointsToTransformForGroundTruthProtocol() +{ + this->InitializePointsToTransformForGroundTruthProtocol(); + + switch (ui->fiducialMarkerConfigurationComboBox->currentIndex()) + { + // case 0 is equal to fiducial marker configuration A (10mm distance) + case 0: + MITK_WARN << "For this marker configuration (10mm) there does not exist a point to transform."; + break; + // case 1 is equal to fiducial marker configuration B (15mm distance) + case 1: + m_PointsToTransformGroundTruthProtocol.at(0)[0] = 130; // = 30mm to end of clipping plate + 100 mm to middle axis of measurement plate + m_PointsToTransformGroundTruthProtocol.at(0)[1] = 15; + m_PointsToTransformGroundTruthProtocol.at(0)[2] = -7; // = 5mm distance to clipping plate + 2mm to base + + m_PointsToTransformGroundTruthProtocol.at(20)[0] = 130; + m_PointsToTransformGroundTruthProtocol.at(20)[1] = 15; + m_PointsToTransformGroundTruthProtocol.at(20)[2] = -27; // = 5mm distance to clipping plate + 2mm to base + 20mm depth + + m_PointsToTransformGroundTruthProtocol.at(40)[0] = 130; + m_PointsToTransformGroundTruthProtocol.at(40)[1] = 15; + m_PointsToTransformGroundTruthProtocol.at(40)[2] = -47; // = 5mm distance to clipping plate + 2mm to base + 40mm depth + + m_PointsToTransformGroundTruthProtocol.at(60)[0] = 130; + m_PointsToTransformGroundTruthProtocol.at(60)[1] = 15; + m_PointsToTransformGroundTruthProtocol.at(60)[2] = -67; // = 5mm distance to clipping plate + 2mm to base + 60mm depth + + m_PointsToTransformGroundTruthProtocol.at(80)[0] = 130; + m_PointsToTransformGroundTruthProtocol.at(80)[1] = 15; + m_PointsToTransformGroundTruthProtocol.at(80)[2] = -87; // = 5mm distance to clipping plate + 2mm to base + 80mm depth + + m_PointsToTransformGroundTruthProtocol.at(100)[0] = 130; + m_PointsToTransformGroundTruthProtocol.at(100)[1] = 15; + m_PointsToTransformGroundTruthProtocol.at(100)[2] = -107; // = 5mm distance to clipping plate + 2mm to base + 100mm depth + + break; + // case 2 is equal to fiducial marker configuration C (20mm distance) + case 2: + m_PointsToTransformGroundTruthProtocol.at(0)[0] = 135; // = 20 + 15mm to end of clipping plate + 100 mm to middle axis of measurement plate + m_PointsToTransformGroundTruthProtocol.at(0)[1] = 20; + m_PointsToTransformGroundTruthProtocol.at(0)[2] = -9; // = 7mm distance to clipping plate + 2mm to base + + m_PointsToTransformGroundTruthProtocol.at(20)[0] = 135; + m_PointsToTransformGroundTruthProtocol.at(20)[1] = 20; + m_PointsToTransformGroundTruthProtocol.at(20)[2] = -29; // = 7mm distance to clipping plate + 2mm to base + 20mm depth + + m_PointsToTransformGroundTruthProtocol.at(40)[0] = 135; + m_PointsToTransformGroundTruthProtocol.at(40)[1] = 20; + m_PointsToTransformGroundTruthProtocol.at(40)[2] = -49; // = 7mm distance to clipping plate + 2mm to base + 40mm depth + + m_PointsToTransformGroundTruthProtocol.at(60)[0] = 135; + m_PointsToTransformGroundTruthProtocol.at(60)[1] = 20; + m_PointsToTransformGroundTruthProtocol.at(60)[2] = -69; // = 7mm distance to clipping plate + 2mm to base + 60mm depth + + m_PointsToTransformGroundTruthProtocol.at(80)[0] = 135; + m_PointsToTransformGroundTruthProtocol.at(80)[1] = 20; + m_PointsToTransformGroundTruthProtocol.at(80)[2] = -89; // = 7mm distance to clipping plate + 2mm to base + 80mm depth + + m_PointsToTransformGroundTruthProtocol.at(100)[0] = 135; + m_PointsToTransformGroundTruthProtocol.at(100)[1] = 20; + m_PointsToTransformGroundTruthProtocol.at(100)[2] = -109; // = 7mm distance to clipping plate + 2mm to base + 100mm depth + break; + } +} + +void QmitkUSNavigationStepCtUsRegistration::TransformPointsGroundTruthProtocol() +{ + if (m_GroundTruthProtocolTransformedPoints.find(0) == m_GroundTruthProtocolTransformedPoints.end()) + { + mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); + pointSet->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(0))); + m_GroundTruthProtocolTransformedPoints.insert(std::pair(0, pointSet)); + } + else + { + m_GroundTruthProtocolTransformedPoints.at(0)->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(0))); + } + + if (m_GroundTruthProtocolTransformedPoints.find(20) == m_GroundTruthProtocolTransformedPoints.end()) + { + mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); + pointSet->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(20))); + m_GroundTruthProtocolTransformedPoints.insert(std::pair(20, pointSet)); + } + else + { + m_GroundTruthProtocolTransformedPoints.at(20)->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(20))); + } + + if (m_GroundTruthProtocolTransformedPoints.find(40) == m_GroundTruthProtocolTransformedPoints.end()) + { + mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); + pointSet->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(40))); + m_GroundTruthProtocolTransformedPoints.insert(std::pair(40, pointSet)); + } + else + { + m_GroundTruthProtocolTransformedPoints.at(40)->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(40))); + } + + if (m_GroundTruthProtocolTransformedPoints.find(60) == m_GroundTruthProtocolTransformedPoints.end()) + { + mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); + pointSet->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(60))); + m_GroundTruthProtocolTransformedPoints.insert(std::pair(60, pointSet)); + } + else + { + m_GroundTruthProtocolTransformedPoints.at(60)->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(60))); + } + + if (m_GroundTruthProtocolTransformedPoints.find(80) == m_GroundTruthProtocolTransformedPoints.end()) + { + mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); + pointSet->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(80))); + m_GroundTruthProtocolTransformedPoints.insert(std::pair(80, pointSet)); + } + else + { + m_GroundTruthProtocolTransformedPoints.at(80)->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(80))); + } + + if (m_GroundTruthProtocolTransformedPoints.find(100) == m_GroundTruthProtocolTransformedPoints.end()) + { + mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); + pointSet->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(100))); + m_GroundTruthProtocolTransformedPoints.insert(std::pair(100, pointSet)); + } + else + { + m_GroundTruthProtocolTransformedPoints.at(100)->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(m_PointsToTransformGroundTruthProtocol.at(100))); + } + +} + +void QmitkUSNavigationStepCtUsRegistration::AddTransformedPointsToDataStorage() +{ + if (m_GroundTruthProtocolTransformedPoints.find(0) == m_GroundTruthProtocolTransformedPoints.end() || + m_GroundTruthProtocolTransformedPoints.find(20) == m_GroundTruthProtocolTransformedPoints.end() || + m_GroundTruthProtocolTransformedPoints.find(40) == m_GroundTruthProtocolTransformedPoints.end() || + m_GroundTruthProtocolTransformedPoints.find(60) == m_GroundTruthProtocolTransformedPoints.end() || + m_GroundTruthProtocolTransformedPoints.find(80) == m_GroundTruthProtocolTransformedPoints.end() || + m_GroundTruthProtocolTransformedPoints.find(100) == m_GroundTruthProtocolTransformedPoints.end()) + { + QMessageBox msgBox; + msgBox.setText("Cannot add transformed Points to DataStorage because they do not exist.\ + Stopping evaluation the protocol."); + msgBox.exec(); + return; + } + + std::string nameNode0mm = "GroundTruthProt-Depth0mm"; + std::string nameNode20mm = "GroundTruthProt-Depth20mm"; + std::string nameNode40mm = "GroundTruthProt-Depth40mm"; + std::string nameNode60mm = "GroundTruthProt-Depth60mm"; + std::string nameNode80mm = "GroundTruthProt-Depth80mm"; + std::string nameNode100mm = "GroundTruthProt-Depth100mm"; + + //Add transformed points of depth 0mm to the data storage + mitk::DataNode::Pointer node0mm = this->GetDataStorage()->GetNamedNode(nameNode0mm); + if (node0mm.IsNull()) + { + node0mm = mitk::DataNode::New(); + node0mm->SetName(nameNode0mm); + node0mm->SetData(m_GroundTruthProtocolTransformedPoints.at(0)); + this->GetDataStorage()->Add(node0mm); + } + else + { + node0mm->SetData(m_GroundTruthProtocolTransformedPoints.at(0)); + this->GetDataStorage()->Modified(); + } + + if(ui->protocolEvaluationTypeComboBox->currentText().compare("PLANE") == 0 ) + { + //Add transformed points of depth 20mm to the data storage + mitk::DataNode::Pointer node20mm = this->GetDataStorage()->GetNamedNode(nameNode20mm); + if (node20mm.IsNull()) + { + node20mm = mitk::DataNode::New(); + node20mm->SetName(nameNode20mm); + node20mm->SetData(m_GroundTruthProtocolTransformedPoints.at(20)); + this->GetDataStorage()->Add(node20mm); + } + else + { + node20mm->SetData(m_GroundTruthProtocolTransformedPoints.at(20)); + this->GetDataStorage()->Modified(); + } + + //Add transformed points of depth 40mm to the data storage + mitk::DataNode::Pointer node40mm = this->GetDataStorage()->GetNamedNode(nameNode40mm); + if (node40mm.IsNull()) + { + node40mm = mitk::DataNode::New(); + node40mm->SetName(nameNode40mm); + node40mm->SetData(m_GroundTruthProtocolTransformedPoints.at(40)); + this->GetDataStorage()->Add(node40mm); + } + else + { + node40mm->SetData(m_GroundTruthProtocolTransformedPoints.at(40)); + this->GetDataStorage()->Modified(); + } + + //Add transformed points of depth 60mm to the data storage + mitk::DataNode::Pointer node60mm = this->GetDataStorage()->GetNamedNode(nameNode60mm); + if (node60mm.IsNull()) + { + node60mm = mitk::DataNode::New(); + node60mm->SetName(nameNode60mm); + node60mm->SetData(m_GroundTruthProtocolTransformedPoints.at(60)); + this->GetDataStorage()->Add(node60mm); + } + else + { + node60mm->SetData(m_GroundTruthProtocolTransformedPoints.at(60)); + this->GetDataStorage()->Modified(); + } + + //Add transformed points of depth 80mm to the data storage + mitk::DataNode::Pointer node80mm = this->GetDataStorage()->GetNamedNode(nameNode80mm); + if (node80mm.IsNull()) + { + node80mm = mitk::DataNode::New(); + node80mm->SetName(nameNode80mm); + node80mm->SetData(m_GroundTruthProtocolTransformedPoints.at(80)); + this->GetDataStorage()->Add(node80mm); + } + else + { + node80mm->SetData(m_GroundTruthProtocolTransformedPoints.at(80)); + this->GetDataStorage()->Modified(); + } + + //Add transformed points of depth 100mm to the data storage + mitk::DataNode::Pointer node100mm = this->GetDataStorage()->GetNamedNode(nameNode100mm); + if (node100mm.IsNull()) + { + node100mm = mitk::DataNode::New(); + node100mm->SetName(nameNode100mm); + node100mm->SetData(m_GroundTruthProtocolTransformedPoints.at(100)); + this->GetDataStorage()->Add(node100mm); + } + else + { + node100mm->SetData(m_GroundTruthProtocolTransformedPoints.at(100)); + this->GetDataStorage()->Modified(); + } + } + //Do a global reinit + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); +} + +double QmitkUSNavigationStepCtUsRegistration::CalculateMeanFRE() +{ + double meanFRE = 0.0; + for (unsigned int counter = 0; counter < m_GroundTruthProtocolFRE.size(); ++counter) + { + meanFRE += m_GroundTruthProtocolFRE[counter]; + } + + return meanFRE / m_GroundTruthProtocolFRE.size(); +} + +double QmitkUSNavigationStepCtUsRegistration::CalculateStandardDeviationOfFRE(double meanFRE) +{ + double variance = 0.0; + + for (unsigned int counter = 0; counter < m_GroundTruthProtocolFRE.size(); ++counter) + { + variance += ((meanFRE - m_GroundTruthProtocolFRE[counter]) * (meanFRE - m_GroundTruthProtocolFRE[counter])); + } + variance /= m_GroundTruthProtocolFRE.size(); // calculate the empirical variance (n) and not the sampling variance (n-1) + + return sqrt(variance); +} + +void QmitkUSNavigationStepCtUsRegistration::CalculateGroundTruthProtocolTRE() +{ + if (m_GroundTruthProtocolTransformedPoints.find(0) == m_GroundTruthProtocolTransformedPoints.end() || + m_GroundTruthProtocolTransformedPoints.find(20) == m_GroundTruthProtocolTransformedPoints.end() || + m_GroundTruthProtocolTransformedPoints.find(40) == m_GroundTruthProtocolTransformedPoints.end() || + m_GroundTruthProtocolTransformedPoints.find(60) == m_GroundTruthProtocolTransformedPoints.end() || + m_GroundTruthProtocolTransformedPoints.find(80) == m_GroundTruthProtocolTransformedPoints.end() || + m_GroundTruthProtocolTransformedPoints.find(100) == m_GroundTruthProtocolTransformedPoints.end()) + { + QMessageBox msgBox; + msgBox.setText("Cannot calculate TRE of Ground-Truth-Protocol because points were not transformed."); + msgBox.exec(); + return; + } + + // clear the std::map containing possibly data of earlier TRE calculations + m_GroundTruthProtocolTRE.clear(); + // loop through all existing point sets containing the transformed points + for (int counter = 0; + m_GroundTruthProtocolTransformedPoints.find(counter) != m_GroundTruthProtocolTransformedPoints.end(); + counter += 20) + { + //calculate the middle point of the point set + mitk::PointSet::Pointer pointSet = m_GroundTruthProtocolTransformedPoints.at(counter); + mitk::Point3D middlePoint; + middlePoint[0] = 0.0; + middlePoint[1] = 0.0; + middlePoint[2] = 0.0; + + for (int position = 0; position < pointSet->GetSize(); ++position) + { + middlePoint[0] += pointSet->GetPoint(position)[0]; + middlePoint[1] += pointSet->GetPoint(position)[1]; + middlePoint[2] += pointSet->GetPoint(position)[2]; + } + middlePoint[0] /= pointSet->GetSize(); + middlePoint[1] /= pointSet->GetSize(); + middlePoint[2] /= pointSet->GetSize(); + MITK_INFO << "Calculated MiddlePoint: " << middlePoint; + + //sum up the euclidean distances between the middle point and each transformed point + double meanDistance = 0.0; + for (int position = 0; position < pointSet->GetSize(); ++position) + { + meanDistance += middlePoint.SquaredEuclideanDistanceTo(pointSet->GetPoint(position)); + MITK_INFO << "SquaredEuclideanDistance: " << middlePoint.SquaredEuclideanDistanceTo(pointSet->GetPoint(position)); + } + + meanDistance /= pointSet->GetSize(); // this can be interpreted as empirical variance + // the root of the empirical variance can be interpreted as the protocols registration TRE + m_GroundTruthProtocolTRE.insert(std::pair(counter, sqrt(meanDistance))); + MITK_INFO << "Ground-Truth-Protocol TRE: " << sqrt(meanDistance); + } + +} + +void QmitkUSNavigationStepCtUsRegistration::EliminateTooSmallLabeledObjects( + ImageType::Pointer binaryImage) +{ + BinaryImageToShapeLabelMapFilterType::OutputImageType::Pointer labelMap = + m_BinaryImageToShapeLabelMapFilter->GetOutput(); + double voxelVolume = this->GetVoxelVolume(); + double fiducialVolume; + unsigned int numberOfPixels; + + if (ui->fiducialDiameter3mmRadioButton->isChecked()) + { + fiducialVolume = this->GetFiducialVolume(1.5); + numberOfPixels = ceil(fiducialVolume / voxelVolume); + } + else + { + fiducialVolume = this->GetFiducialVolume(2.5); + numberOfPixels = ceil(fiducialVolume / voxelVolume); + } + + MITK_INFO << "Voxel Volume = " << voxelVolume << "; Fiducial Volume = " << fiducialVolume; + MITK_INFO << "Number of pixels = " << numberOfPixels; + + labelMap = m_BinaryImageToShapeLabelMapFilter->GetOutput(); + // The output of this filter is an itk::LabelMap, which contains itk::LabelObject's + MITK_INFO << "There are " << labelMap->GetNumberOfLabelObjects() << " objects."; + + // Loop over each region + for (int i = labelMap->GetNumberOfLabelObjects() - 1; i >= 0; --i) + { + // Get the ith region + BinaryImageToShapeLabelMapFilterType::OutputImageType::LabelObjectType* labelObject = labelMap->GetNthLabelObject(i); + MITK_INFO << "Object " << i << " contains " << labelObject->Size() << " pixel"; + + //TODO: Threshold-Wert evtl. experimentell besser abstimmen, + // um zu verhindern, dass durch Threshold wahre Fiducial-Kandidaten elimiert werden. + if (labelObject->Size() < numberOfPixels * 0.8) + { + for (unsigned int pixelId = 0; pixelId < labelObject->Size(); pixelId++) + { + binaryImage->SetPixel(labelObject->GetIndex(pixelId), 0); + } + labelMap->RemoveLabelObject(labelObject); + } + } +} + +bool QmitkUSNavigationStepCtUsRegistration::EliminateFiducialCandidatesByEuclideanDistances() +{ + if (m_CentroidsOfFiducialCandidates.size() < NUMBER_FIDUCIALS_NEEDED) + { + return false; + } + + for (unsigned int counter = 0; counter < m_CentroidsOfFiducialCandidates.size(); ++counter) + { + int amountOfAcceptedFiducials = 0; + mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(counter)); + //Loop through all fiducial candidates and calculate the distance between the chosen fiducial + // candidate and the other candidates. For each candidate with a right distance between + // Configuration A: 7.93mm and 31.0mm (10 mm distance between fiducial centers) or + // Configuration B: 11.895mm and 45.0mm (15 mm distance between fiducial centers) or + // Configuration C: 15.86mm and 59.0mm (20 mm distance between fiducial centers) + // + // increase the amountOfAcceptedFiducials. + for (unsigned int position = 0; position < m_CentroidsOfFiducialCandidates.size(); ++position) + { + if (position == counter) + { + continue; + } + mitk::Point3D otherCentroid(m_CentroidsOfFiducialCandidates.at(position)); + double distance = fiducialCentroid.EuclideanDistanceTo(otherCentroid); + + switch (ui->fiducialMarkerConfigurationComboBox->currentIndex()) + { + // case 0 is equal to fiducial marker configuration A (10mm distance) + case 0: + if (distance > 7.93 && distance < 31.0) + { + ++amountOfAcceptedFiducials; + } + break; + // case 1 is equal to fiducial marker configuration B (15mm distance) + case 1: + if (distance > 11.895 && distance < 45.0) + { + ++amountOfAcceptedFiducials; + } + break; + // case 2 is equal to fiducial marker configuration C (20mm distance) + case 2: + if (distance > 15.86 && distance < 59.0) + { + ++amountOfAcceptedFiducials; + } + break; + } + } + //The amountOfAcceptedFiducials must be at least 7. Otherwise delete the fiducial candidate + // from the list of candidates. + if (amountOfAcceptedFiducials < NUMBER_FIDUCIALS_NEEDED - 1) + { + MITK_INFO << "Deleting fiducial candidate at position: " << + m_CentroidsOfFiducialCandidates.at(counter); + m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + counter); + if (m_CentroidsOfFiducialCandidates.size() < NUMBER_FIDUCIALS_NEEDED ) + { + return false; + } + counter = -1; + } + } + + //Classify the rested fiducial candidates by its characteristic Euclidean distances + // between the canidates and remove all candidates with a false distance configuration: + this->ClassifyFiducialCandidates(); + return true; +} + +void QmitkUSNavigationStepCtUsRegistration::ClassifyFiducialCandidates() +{ + MITK_INFO << "ClassifyFiducialCandidates()"; + std::vector fiducialCandidatesToBeRemoved; + std::vector> distanceVectorsFiducials; + this->CalculateDistancesBetweenFiducials(distanceVectorsFiducials); + + for (unsigned int counter = 0; counter < distanceVectorsFiducials.size(); ++counter) + { + int distanceA = 0; // => 10,00mm distance + int distanceB = 0; // => 14,14mm distance + int distanceC = 0; // => 17,32mm distance + int distanceD = 0; // => 22,36mm distance + int distanceE = 0; // => 24,49mm distance + int distanceF = 0; // => 28,28mm distance + + std::vector &distances = distanceVectorsFiducials.at(counter); + for (unsigned int number = 0; number < distances.size(); ++number) + { + double &distance = distances.at(number); + switch (ui->fiducialMarkerConfigurationComboBox->currentIndex()) + { + // case 0 is equal to fiducial marker configuration A (10mm distance) + case 0: + if (distance > 7.93 && distance <= 12.07) + { + ++distanceA; + } + else if (distance > 12.07 && distance <= 15.73) + { + ++distanceB; + } + else if (distance > 15.73 && distance <= 19.84) + { + ++distanceC; + } + else if (distance > 19.84 && distance <= 23.425) + { + ++distanceD; + } + else if (distance > 23.425 && distance <= 26.385) + { + ++distanceE; + } + else if (distance > 26.385 && distance <= 31.00) + { + ++distanceF; + } + break; + + // case 1 is equal to fiducial marker configuration B (15mm distance) + case 1: + if (distance > 11.895 && distance <= 18.105) + { + ++distanceA; + } + else if (distance > 18.105 && distance <= 23.595) + { + ++distanceB; + } + else if (distance > 23.595 && distance <= 29.76) + { + ++distanceC; + } + else if (distance > 29.76 && distance <= 35.1375) + { + ++distanceD; + if (distance > 33.54) + { + ++distanceE; + } + } + else if (distance > 35.1375 && distance <= 39.5775) + { + ++distanceE; + if (distance < 36.735) + { + ++distanceD; + } + } + else if (distance > 39.5775 && distance <= 45.00) + { + ++distanceF; + } + break; + + // case 2 is equal to fiducial marker configuration C (20mm distance) + case 2: + if (distance > 15.86 && distance <= 24.14) + { + ++distanceA; + } + else if (distance > 24.14 && distance <= 31.46) + { + ++distanceB; + } + else if (distance > 31.46 && distance <= 39.68) + { + ++distanceC; + } + else if (distance > 39.68 && distance <= 46.85) + { + ++distanceD; + } + else if (distance > 46.85 && distance <= 52.77) + { + ++distanceE; + } + else if (distance > 52.77 && distance <= 59.00) + { + ++distanceF; + } + break; + } + }// End for-loop distances-vector + + //Now, having looped through all distances of one fiducial candidate, check + // if the combination of different distances is known. The >= is due to the + // possible occurrence of other fiducial candidates that have an distance equal to + // one of the distances A - E. However, false fiducial candidates outside + // the fiducial marker does not have the right distance configuration: + if (((distanceA >= 2 && distanceD >= 2 && distanceE >= 2 && distanceF >= 1) || + (distanceA >= 1 && distanceB >= 2 && distanceC >= 1 && distanceD >= 2 && distanceE >= 1) || + (distanceB >= 2 && distanceD >= 4 && distanceF >= 1) || + (distanceA >= 1 && distanceB >= 1 && distanceD >= 3 && distanceE >= 1 && distanceF >= 1)) == false) + { + MITK_INFO << "Detected fiducial candidate with unknown distance configuration."; + fiducialCandidatesToBeRemoved.push_back(counter); + } + } + for (int count = fiducialCandidatesToBeRemoved.size() - 1; count >= 0; --count) + { + MITK_INFO << "Removing fiducial candidate " << fiducialCandidatesToBeRemoved.at(count); + m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + + fiducialCandidatesToBeRemoved.at(count)); + } +} + +void QmitkUSNavigationStepCtUsRegistration::GetCentroidsOfLabeledObjects() +{ + MITK_INFO << "GetCentroidsOfLabeledObjects()"; + BinaryImageToShapeLabelMapFilterType::OutputImageType::Pointer labelMap = + m_BinaryImageToShapeLabelMapFilter->GetOutput(); + for (int i = labelMap->GetNumberOfLabelObjects() - 1; i >= 0; --i) + { + // Get the ith region + BinaryImageToShapeLabelMapFilterType::OutputImageType::LabelObjectType* labelObject = labelMap->GetNthLabelObject(i); + MITK_INFO << "Object " << i << " contains " << labelObject->Size() << " pixel"; + + mitk::Vector3D centroid; + centroid[0] = labelObject->GetCentroid()[0]; + centroid[1] = labelObject->GetCentroid()[1]; + centroid[2] = labelObject->GetCentroid()[2]; + m_CentroidsOfFiducialCandidates.push_back(centroid); + } + //evtl. for later: itk::LabelMapOverlayImageFilter +} + +void QmitkUSNavigationStepCtUsRegistration::NumerateFiducialMarks() +{ + MITK_INFO << "NumerateFiducialMarks()"; + bool successFiducialNo1; + bool successFiducialNo4; + bool successFiducialNo2And3; + bool successFiducialNo5; + bool successFiducialNo8; + bool successFiducialNo6; + bool successFiducialNo7; + + std::vector> distanceVectorsFiducials; + this->CalculateDistancesBetweenFiducials(distanceVectorsFiducials); + successFiducialNo1 = this->FindFiducialNo1(distanceVectorsFiducials); + successFiducialNo4 = this->FindFiducialNo4(distanceVectorsFiducials); + successFiducialNo2And3 = this->FindFiducialNo2And3(); + successFiducialNo5 = this->FindFiducialNo5(); + successFiducialNo8 = this->FindFiducialNo8(); + successFiducialNo6 = this->FindFiducialNo6(); + successFiducialNo7 = this->FindFiducialNo7(); + + if (!successFiducialNo1 || !successFiducialNo4 || !successFiducialNo2And3 || + !successFiducialNo5 || !successFiducialNo8 || !successFiducialNo6 || !successFiducialNo7) + { + QMessageBox msgBox; + msgBox.setText("Cannot numerate/localize all fiducials successfully."); + msgBox.exec(); + return; + } + + if (m_MarkerFloatingImageCoordinateSystemPointSet.IsNull()) + { + m_MarkerFloatingImageCoordinateSystemPointSet = mitk::PointSet::New(); + } + else if (m_MarkerFloatingImageCoordinateSystemPointSet->GetSize() != 0) + { + m_MarkerFloatingImageCoordinateSystemPointSet->Clear(); + } + + for (unsigned int counter = 1; counter <= m_FiducialMarkerCentroids.size(); ++counter) + { + m_MarkerFloatingImageCoordinateSystemPointSet->InsertPoint(counter - 1, m_FiducialMarkerCentroids.at(counter)); + } + if( !m_PerformingGroundTruthProtocolEvaluation ) + { + mitk::DataNode::Pointer node = mitk::DataNode::New(); + node->SetData(m_MarkerFloatingImageCoordinateSystemPointSet); + node->SetName("MarkerFloatingImageCSPointSet"); + //node->SetFloatProperty("pointsize", 5.0); + this->GetDataStorage()->Add(node); + } +} + +void QmitkUSNavigationStepCtUsRegistration::CalculateDistancesBetweenFiducials(std::vector>& distanceVectorsFiducials) +{ + std::vector distancesBetweenFiducials; + + for (unsigned int i = 0; i < m_CentroidsOfFiducialCandidates.size(); ++i) + { + distancesBetweenFiducials.clear(); + mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(i)); + for (unsigned int n = 0; n < m_CentroidsOfFiducialCandidates.size(); ++n) + { + mitk::Point3D otherCentroid(m_CentroidsOfFiducialCandidates.at(n)); + distancesBetweenFiducials.push_back(fiducialCentroid.EuclideanDistanceTo(otherCentroid)); + } + //Sort the distances from low to big numbers + std::sort(distancesBetweenFiducials.begin(), distancesBetweenFiducials.end()); + //First entry of the distance vector must be 0, so erase it + if (distancesBetweenFiducials.at(0) == 0.0) + { + distancesBetweenFiducials.erase(distancesBetweenFiducials.begin()); + } + //Add the distance vector to the collecting distances vector + distanceVectorsFiducials.push_back(distancesBetweenFiducials); + } + + for (unsigned int i = 0; i < distanceVectorsFiducials.size(); ++i) + { + MITK_INFO << "Vector " << i << ":"; + for (unsigned int k = 0; k < distanceVectorsFiducials.at(i).size(); ++k) + { + MITK_INFO << distanceVectorsFiducials.at(i).at(k); + } + } +} + +bool QmitkUSNavigationStepCtUsRegistration::FindFiducialNo1(std::vector>& distanceVectorsFiducials) +{ + for (unsigned int i = 0; i < distanceVectorsFiducials.size(); ++i) + { + std::vector &distances = distanceVectorsFiducials.at(i); + if (distances.size() < NUMBER_FIDUCIALS_NEEDED - 1 ) + { + MITK_WARN << "Cannot find fiducial 1, there aren't found enough fiducial candidates."; + return false; + } + double characteristicDistanceAWithUpperMargin = this->GetCharacteristicDistanceAWithUpperMargin(); + + if (distances.at(0) <= characteristicDistanceAWithUpperMargin && + distances.at(1) <= characteristicDistanceAWithUpperMargin) + { + MITK_INFO << "Found Fiducial 1 (PointSet number " << i << ")"; + m_FiducialMarkerCentroids.insert( std::pair(1, m_CentroidsOfFiducialCandidates.at(i))); + distanceVectorsFiducials.erase(distanceVectorsFiducials.begin() + i); + m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + i); + return true; + } + } + return false; +} + +bool QmitkUSNavigationStepCtUsRegistration::FindFiducialNo2And3() +{ + if (m_FiducialMarkerCentroids.find(1) == m_FiducialMarkerCentroids.end() ) + { + MITK_WARN << "Cannot find fiducial No 2 and 3. Before must be found fiducial No 1."; + return false; + } + + mitk::Point3D fiducialNo1(m_FiducialMarkerCentroids.at(1)); + mitk::Vector3D fiducialVectorA; + mitk::Vector3D fiducialVectorB; + mitk::Point3D fiducialPointA; + mitk::Point3D fiducialPointB; + bool foundFiducialA = false; + bool foundFiducialB = false; + mitk::Vector3D vectorFiducial1ToFiducialA; + mitk::Vector3D vectorFiducial1ToFiducialB; + + for (unsigned int i = 0; i < m_CentroidsOfFiducialCandidates.size(); ++i) + { + mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(i)); + double distance = fiducialNo1.EuclideanDistanceTo(fiducialCentroid); + if (distance <= this->GetCharacteristicDistanceAWithUpperMargin()) + { + fiducialVectorA = m_CentroidsOfFiducialCandidates.at(i); + fiducialPointA = fiducialCentroid; + m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + i); + foundFiducialA = true; + break; + } + } + + for (unsigned int i = 0; i < m_CentroidsOfFiducialCandidates.size(); ++i) + { + mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(i)); + double distance = fiducialNo1.EuclideanDistanceTo(fiducialCentroid); + if (distance <= this->GetCharacteristicDistanceAWithUpperMargin()) + { + fiducialVectorB = m_CentroidsOfFiducialCandidates.at(i); + fiducialPointB = fiducialCentroid; + m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + i); + foundFiducialB = true; + break; + } + } + + if (!foundFiducialA || !foundFiducialB) + { + MITK_WARN << "Cannot identify fiducial candidates 2 and 3"; + return false; + } + else if (m_CentroidsOfFiducialCandidates.size() == 0) + { + MITK_WARN << "Too less fiducials detected. Cannot identify fiducial candidates 2 and 3"; + return false; + } + + vectorFiducial1ToFiducialA = fiducialVectorA - m_FiducialMarkerCentroids.at(1); + vectorFiducial1ToFiducialB = fiducialVectorB - m_FiducialMarkerCentroids.at(1); + + vnl_vector crossProductVnl = vnl_cross_3d(vectorFiducial1ToFiducialA.GetVnlVector(), vectorFiducial1ToFiducialB.GetVnlVector()); + mitk::Vector3D crossProduct; + crossProduct.SetVnlVector(crossProductVnl); + + mitk::Vector3D vectorFiducial1ToRandomLeftFiducial = m_CentroidsOfFiducialCandidates.at(0) - m_FiducialMarkerCentroids.at(1); + + double scalarProduct = (crossProduct * vectorFiducial1ToRandomLeftFiducial) / + (crossProduct.GetNorm() * vectorFiducial1ToRandomLeftFiducial.GetNorm()); + + double alpha = acos(scalarProduct) * 57.29578; //Transform into degree + MITK_INFO << "Scalar Product = " << alpha; + + if (alpha <= 90) + { + m_FiducialMarkerCentroids[3] = fiducialVectorA; + m_FiducialMarkerCentroids[2] = fiducialVectorB; + } + else + { + m_FiducialMarkerCentroids[2] = fiducialVectorA; + m_FiducialMarkerCentroids[3] = fiducialVectorB; + } + + MITK_INFO << "Found Fiducial 2, PointSet: " << m_FiducialMarkerCentroids.at(2); + MITK_INFO << "Found Fiducial 3, PointSet: " << m_FiducialMarkerCentroids.at(3); + + return true; +} + +bool QmitkUSNavigationStepCtUsRegistration::FindFiducialNo4(std::vector>& distanceVectorsFiducials) +{ + double characteristicDistanceBWithLowerMargin = this->GetCharacteristicDistanceBWithLowerMargin(); + double characteristicDistanceBWithUpperMargin = this->GetCharacteristicDistanceBWithUpperMargin(); + + for (unsigned int i = 0; i < distanceVectorsFiducials.size(); ++i) + { + std::vector &distances = distanceVectorsFiducials.at(i); + if (distances.size() < NUMBER_FIDUCIALS_NEEDED - 1) + { + MITK_WARN << "Cannot find fiducial 4, there aren't found enough fiducial candidates."; + return false; + } + + if (distances.at(0) > characteristicDistanceBWithLowerMargin && + distances.at(0) <= characteristicDistanceBWithUpperMargin && + distances.at(1) > characteristicDistanceBWithLowerMargin && + distances.at(1) <= characteristicDistanceBWithUpperMargin) + { + MITK_INFO << "Found Fiducial 4 (PointSet number " << i << ")"; + m_FiducialMarkerCentroids.insert(std::pair(4, m_CentroidsOfFiducialCandidates.at(i))); + distanceVectorsFiducials.erase(distanceVectorsFiducials.begin() + i); + m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + i); + return true; + } + } + return false; +} + +bool QmitkUSNavigationStepCtUsRegistration::FindFiducialNo5() +{ + if (m_FiducialMarkerCentroids.find(2) == m_FiducialMarkerCentroids.end()) + { + MITK_WARN << "To find fiducial No 5, fiducial No 2 has to be found before."; + return false; + } + + double characteristicDistanceBWithUpperMargin = this->GetCharacteristicDistanceBWithUpperMargin(); + + mitk::Point3D fiducialNo2(m_FiducialMarkerCentroids.at(2)); + + for (unsigned int counter = 0; counter < m_CentroidsOfFiducialCandidates.size(); ++counter) + { + mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(counter)); + double distance = fiducialNo2.EuclideanDistanceTo(fiducialCentroid); + if (distance <= characteristicDistanceBWithUpperMargin) + { + m_FiducialMarkerCentroids[5] = m_CentroidsOfFiducialCandidates.at(counter); + m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + counter); + MITK_INFO << "Found Fiducial No 5, PointSet: " << m_FiducialMarkerCentroids[5]; + return true; + } + } + + MITK_WARN << "Cannot find fiducial No 5."; + return false; +} + +bool QmitkUSNavigationStepCtUsRegistration::FindFiducialNo6() +{ + if (m_FiducialMarkerCentroids.find(5) == m_FiducialMarkerCentroids.end()) + { + MITK_WARN << "To find fiducial No 6, fiducial No 5 has to be found before."; + return false; + } + + double characteristicDistanceAWithUpperMargin = this->GetCharacteristicDistanceAWithUpperMargin(); + + mitk::Point3D fiducialNo5(m_FiducialMarkerCentroids.at(5)); + + for (unsigned int counter = 0; counter < m_CentroidsOfFiducialCandidates.size(); ++counter) + { + mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(counter)); + double distance = fiducialNo5.EuclideanDistanceTo(fiducialCentroid); + if (distance <= characteristicDistanceAWithUpperMargin) + { + m_FiducialMarkerCentroids[6] = m_CentroidsOfFiducialCandidates.at(counter); + m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + counter); + MITK_INFO << "Found Fiducial No 6, PointSet: " << m_FiducialMarkerCentroids[6]; + return true; + } + } + + MITK_WARN << "Cannot find fiducial No 6."; + return false; +} + +bool QmitkUSNavigationStepCtUsRegistration::FindFiducialNo7() +{ + if (m_FiducialMarkerCentroids.find(8) == m_FiducialMarkerCentroids.end()) + { + MITK_WARN << "To find fiducial No 7, fiducial No 8 has to be found before."; + return false; + } + + double characteristicDistanceAWithUpperMargin = this->GetCharacteristicDistanceAWithUpperMargin(); + + mitk::Point3D fiducialNo8(m_FiducialMarkerCentroids.at(8)); + + for (unsigned int counter = 0; counter < m_CentroidsOfFiducialCandidates.size(); ++counter) + { + mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(counter)); + double distance = fiducialNo8.EuclideanDistanceTo(fiducialCentroid); + if (distance <= characteristicDistanceAWithUpperMargin) + { + m_FiducialMarkerCentroids[7] = m_CentroidsOfFiducialCandidates.at(counter); + m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + counter); + MITK_INFO << "Found Fiducial No 7, PointSet: " << m_FiducialMarkerCentroids[7]; + return true; + } + } + + MITK_WARN << "Cannot find fiducial No 7."; + return false; +} + +bool QmitkUSNavigationStepCtUsRegistration::FindFiducialNo8() +{ + if (m_FiducialMarkerCentroids.find(3) == m_FiducialMarkerCentroids.end()) + { + MITK_WARN << "To find fiducial No 8, fiducial No 3 has to be found before."; + return false; + } + + double characteristicDistanceBWithUpperMargin = this->GetCharacteristicDistanceBWithUpperMargin(); + + mitk::Point3D fiducialNo3(m_FiducialMarkerCentroids.at(3)); + + for (unsigned int counter = 0; counter < m_CentroidsOfFiducialCandidates.size(); ++counter) + { + mitk::Point3D fiducialCentroid(m_CentroidsOfFiducialCandidates.at(counter)); + double distance = fiducialNo3.EuclideanDistanceTo(fiducialCentroid); + if (distance <= characteristicDistanceBWithUpperMargin) + { + m_FiducialMarkerCentroids[8] = m_CentroidsOfFiducialCandidates.at(counter); + m_CentroidsOfFiducialCandidates.erase(m_CentroidsOfFiducialCandidates.begin() + counter); + MITK_INFO << "Found Fiducial No 8, PointSet: " << m_FiducialMarkerCentroids[8]; + return true; + } + } + + MITK_WARN << "Cannot find fiducial No 8."; + return false; +} + +void QmitkUSNavigationStepCtUsRegistration::DefineDataStorageImageFilter() +{ + m_IsAPointSetPredicate = mitk::TNodePredicateDataType::New(); + mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); + + auto isSegmentation = mitk::NodePredicateDataType::New("Segment"); + m_IsASurfacePredicate = mitk::NodePredicateDataType::New("Surface"); + + mitk::NodePredicateOr::Pointer validImages = mitk::NodePredicateOr::New(); + validImages->AddPredicate(mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isSegmentation))); + + mitk::NodePredicateNot::Pointer isNotAHelperObject = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true))); + + m_IsOfTypeImagePredicate = mitk::NodePredicateAnd::New(validImages, isNotAHelperObject); + + mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); + mitk::NodePredicateNot::Pointer isNotBinaryPredicate = mitk::NodePredicateNot::New(isBinaryPredicate); + + mitk::NodePredicateAnd::Pointer isABinaryImagePredicate = mitk::NodePredicateAnd::New(m_IsOfTypeImagePredicate, isBinaryPredicate); + mitk::NodePredicateAnd::Pointer isNotABinaryImagePredicate = mitk::NodePredicateAnd::New(m_IsOfTypeImagePredicate, isNotBinaryPredicate); + + m_IsASegmentationImagePredicate = mitk::NodePredicateOr::New(isABinaryImagePredicate, mitk::TNodePredicateDataType::New()); + m_IsAPatientImagePredicate = mitk::NodePredicateAnd::New(isNotABinaryImagePredicate, mitk::NodePredicateNot::New(mitk::TNodePredicateDataType::New())); +} + +void QmitkUSNavigationStepCtUsRegistration::CreateQtPartControl(QWidget *parent) +{ + ui->setupUi(parent); + ui->floatingImageComboBox->SetPredicate(m_IsAPatientImagePredicate); + ui->ctImagesToChooseComboBox->SetPredicate(m_IsAPatientImagePredicate); + ui->segmentationComboBox->SetPredicate(m_IsASegmentationImagePredicate); + ui->selectedSurfaceComboBox->SetPredicate(m_IsASurfacePredicate); + ui->pointSetComboBox->SetPredicate(m_IsAPointSetPredicate); + + // create signal/slot connections + connect(ui->floatingImageComboBox, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), + this, SLOT(OnFloatingImageComboBoxSelectionChanged(const mitk::DataNode*))); + connect(ui->doRegistrationMarkerToImagePushButton, SIGNAL(clicked()), + this, SLOT(OnRegisterMarkerToFloatingImageCS())); + connect(ui->localizeFiducialMarkerPushButton, SIGNAL(clicked()), + this, SLOT(OnLocalizeFiducials())); + connect(ui->visualizeCTtoUSregistrationPushButton, SIGNAL(clicked()), + this, SLOT(OnVisualizeCTtoUSregistration())); + connect(ui->freezeUnfreezePushButton, SIGNAL(clicked()), + this, SLOT(OnFreeze())); + connect(ui->addCtImagePushButton, SIGNAL(clicked()), + this, SLOT(OnAddCtImageClicked())); + connect(ui->removeCtImagePushButton, SIGNAL(clicked()), + this, SLOT(OnRemoveCtImageClicked())); + connect(ui->evaluateProtocolPushButton, SIGNAL(clicked()), + this, SLOT(OnEvaluateGroundTruthFiducialLocalizationProtocol())); + connect(ui->actualizeSegmentationSurfacePSetDataPushButton, SIGNAL(clicked()), + this, SLOT(OnActualizeSegmentationSurfacePointSetData())); + connect(ui->calculateTREPushButton, SIGNAL(clicked()), + this, SLOT(OnGetCursorPosition())); + connect(ui->calculateCenterPushButton, SIGNAL(clicked()), + this, SLOT(OnCalculateCenter())); +} + +void QmitkUSNavigationStepCtUsRegistration::OnFloatingImageComboBoxSelectionChanged(const mitk::DataNode* node) +{ + MITK_INFO << "OnFloatingImageComboBoxSelectionChanged()"; + + if (m_FloatingImage.IsNotNull()) + { + //TODO: Define, what will happen if the imageCT is not null... + } + + if (node == nullptr) + { + this->UnsetFloatingImageGeometry(); + m_FloatingImage = nullptr; + return; + } + + mitk::DataNode* selectedFloatingImage = ui->floatingImageComboBox->GetSelectedNode(); + if (selectedFloatingImage == nullptr) + { + this->UnsetFloatingImageGeometry(); + m_FloatingImage = nullptr; + return; + } + + mitk::Image::Pointer floatingImage = dynamic_cast(selectedFloatingImage->GetData()); + if (floatingImage.IsNull()) + { + MITK_WARN << "Failed to cast selected segmentation node to mitk::Image*"; + this->UnsetFloatingImageGeometry(); + m_FloatingImage = nullptr; + return; + } + + m_FloatingImage = floatingImage; + this->SetFloatingImageGeometryInformation(floatingImage.GetPointer()); +} + +void QmitkUSNavigationStepCtUsRegistration::OnRegisterMarkerToFloatingImageCS() +{ + this->CreateMarkerModelCoordinateSystemPointSet(); + + //Check for initialization + if( m_MarkerModelCoordinateSystemPointSet.IsNull() || + m_MarkerFloatingImageCoordinateSystemPointSet.IsNull() ) + { + MITK_WARN << "Fiducial Landmarks are not initialized yet, cannot register"; + return; + } + + //Retrieve fiducials + if (m_MarkerFloatingImageCoordinateSystemPointSet->GetSize() != m_MarkerModelCoordinateSystemPointSet->GetSize()) + { + MITK_WARN << "Not the same number of fiducials, cannot register"; + return; + } + else if (m_MarkerFloatingImageCoordinateSystemPointSet->GetSize() < 3) + { + MITK_WARN << "Need at least 3 fiducials, cannot register"; + return; + } + + //############### conversion to vtk data types (we will use the vtk landmark based transform) ########################## + //convert point sets to vtk poly data + vtkSmartPointer sourcePoints = vtkSmartPointer::New(); + vtkSmartPointer targetPoints = vtkSmartPointer::New(); + for (int i = 0; iGetSize(); i++) + { + double point[3] = { m_MarkerModelCoordinateSystemPointSet->GetPoint(i)[0], + m_MarkerModelCoordinateSystemPointSet->GetPoint(i)[1], + m_MarkerModelCoordinateSystemPointSet->GetPoint(i)[2] }; + sourcePoints->InsertNextPoint(point); + + double point_targets[3] = { m_MarkerFloatingImageCoordinateSystemPointSet->GetPoint(i)[0], + m_MarkerFloatingImageCoordinateSystemPointSet->GetPoint(i)[1], + m_MarkerFloatingImageCoordinateSystemPointSet->GetPoint(i)[2] }; + targetPoints->InsertNextPoint(point_targets); + } + + //########################### here, the actual transform is computed ########################## + //compute transform + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->SetSourceLandmarks(sourcePoints); + transform->SetTargetLandmarks(targetPoints); + transform->SetModeToRigidBody(); + transform->Modified(); + transform->Update(); + //compute FRE of transform + + double FRE = mitk::StaticIGTHelperFunctions::ComputeFRE(m_MarkerModelCoordinateSystemPointSet, m_MarkerFloatingImageCoordinateSystemPointSet, transform); + MITK_INFO << "FRE: " << FRE << " mm"; + if (m_PerformingGroundTruthProtocolEvaluation) + { + m_GroundTruthProtocolFRE.push_back(FRE); + } + //############################################################################################# + + //############### conversion back to itk/mitk data types ########################## + //convert from vtk to itk data types + itk::Matrix rotationFloat = itk::Matrix(); + itk::Vector translationFloat = itk::Vector(); + itk::Matrix rotationDouble = itk::Matrix(); + itk::Vector translationDouble = itk::Vector(); + + vtkSmartPointer m = transform->GetMatrix(); + for (int k = 0; k<3; k++) for (int l = 0; l<3; l++) + { + rotationFloat[k][l] = m->GetElement(k, l); + rotationDouble[k][l] = m->GetElement(k, l); + + } + for (int k = 0; k<3; k++) + { + translationFloat[k] = m->GetElement(k, 3); + translationDouble[k] = m->GetElement(k, 3); + } + //create mitk affine transform 3D and save it to the class member + m_TransformMarkerCSToFloatingImageCS = mitk::AffineTransform3D::New(); + m_TransformMarkerCSToFloatingImageCS->SetMatrix(rotationDouble); + m_TransformMarkerCSToFloatingImageCS->SetOffset(translationDouble); + MITK_INFO << m_TransformMarkerCSToFloatingImageCS; + //################################################################ + + //############### object is transformed ########################## + //transform surface/image + //only move image if we have one. Sometimes, this widget is used just to register point sets without images. + + /*if (m_ImageNode.IsNotNull()) + { + //first we have to store the original ct image transform to compose it with the new transform later + mitk::AffineTransform3D::Pointer imageTransform = m_ImageNode->GetData()->GetGeometry()->GetIndexToWorldTransform(); + imageTransform->Compose(mitkTransform); + mitk::AffineTransform3D::Pointer newImageTransform = mitk::AffineTransform3D::New(); //create new image transform... setting the composed directly leads to an error + itk::Matrix rotationFloatNew = imageTransform->GetMatrix(); + itk::Vector translationFloatNew = imageTransform->GetOffset(); + newImageTransform->SetMatrix(rotationFloatNew); + newImageTransform->SetOffset(translationFloatNew); + m_ImageNode->GetData()->GetGeometry()->SetIndexToWorldTransform(newImageTransform); + }*/ + + //If this option is set, each point will be transformed and the acutal coordinates of the points change. + + if( !m_PerformingGroundTruthProtocolEvaluation ) + { + mitk::PointSet* pointSet_orig = m_MarkerModelCoordinateSystemPointSet; + mitk::PointSet::Pointer pointSet_moved = mitk::PointSet::New(); + + for (int i = 0; i < pointSet_orig->GetSize(); i++) + { + pointSet_moved->InsertPoint(m_TransformMarkerCSToFloatingImageCS->TransformPoint(pointSet_orig->GetPoint(i))); + } + + pointSet_orig->Clear(); + for (int i = 0; i < pointSet_moved->GetSize(); i++) + pointSet_orig->InsertPoint(pointSet_moved->GetPoint(i)); + + //Do a global reinit + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); + } + +} + +void QmitkUSNavigationStepCtUsRegistration::OnLocalizeFiducials() +{ + m_FiducialMarkerCentroids.clear(); + m_CentroidsOfFiducialCandidates.clear(); + if (m_MarkerFloatingImageCoordinateSystemPointSet.IsNotNull()) + { + m_MarkerFloatingImageCoordinateSystemPointSet->Clear(); + } + + if (!this->FilterFloatingImage()) + { + QMessageBox msgBox; + msgBox.setText("Cannot perform filtering of the image. The floating image = nullptr."); + msgBox.exec(); + return; + } + mitk::AffineTransform3D::Pointer transform = m_FloatingImage->GetGeometry()->GetIndexToWorldTransform(); + MITK_WARN << "IndexToWorldTransform_CTimage = " << transform; + + this->GetCentroidsOfLabeledObjects(); + + if (!this->EliminateFiducialCandidatesByEuclideanDistances() || + m_CentroidsOfFiducialCandidates.size() != NUMBER_FIDUCIALS_NEEDED) + { + QMessageBox msgBox; + QString text = QString("Have found %1 instead of 8 fiducial candidates.\ + Cannot perform fiducial localization procedure.").arg(m_CentroidsOfFiducialCandidates.size()); + msgBox.setText(text); + msgBox.exec(); + return; + } + + //Before calling NumerateFiducialMarks it must be sure, + // that there rested only 8 fiducial candidates. + this->NumerateFiducialMarks(); +} + +void QmitkUSNavigationStepCtUsRegistration::OnVisualizeCTtoUSregistration() +{ + emit this->ActualizeCtToUsRegistrationWidget(); + + mitk::DataNode* segmentationNode = ui->segmentationComboBox->GetSelectedNode(); + if (segmentationNode == nullptr) + { + QMessageBox msgBox; + msgBox.setText("Cannot visualize CT-to-US registration. There is no segmentation selected."); + msgBox.exec(); + return; + } + mitk::AffineTransform3D::Pointer transform = segmentationNode->GetData()->GetGeometry()->GetIndexToWorldTransform(); + MITK_WARN << "IndexToWorldTransform_segmentation = " << transform; + + mitk::DataNode* surfaceNode = ui->selectedSurfaceComboBox->GetSelectedNode(); + if (surfaceNode == nullptr) + { + QMessageBox msgBox; + msgBox.setText("Cannot visualize CT-to-US registration. There is no surface selected."); + msgBox.exec(); + return; + } + + mitk::DataNode* pointSetNode = ui->pointSetComboBox->GetSelectedNode(); + if (pointSetNode == nullptr) + { + QMessageBox msgBox; + msgBox.setText("Cannot visualize CT-to-US registration. There is no pointSet selected."); + msgBox.exec(); + return; + } + + if (this->GetCombinedModality(false).IsNull()) + { + QMessageBox msgBox; + msgBox.setText("CombinedModality not yet set.\nPlease try again and click on the button."); + msgBox.exec(); + return; + } + + if (m_FloatingImageToUltrasoundRegistrationFilter.IsNull()) + { + QMessageBox msgBox; + msgBox.setText("Cannot visualize CT-to-US registration.\ + The FloatingImageToUltrasoundRegistrationFilter is not initialized."); + msgBox.exec(); + return; + } + //Set the transformation from marker-CS to the sensor-CS accordingly to the chosen user-option + m_FloatingImageToUltrasoundRegistrationFilter + ->InitializeTransformationMarkerCSToSensorCS(ui->useNdiTrackerCheckBox->isChecked()); + m_FloatingImageToUltrasoundRegistrationFilter->SetPointSet(pointSetNode); + m_FloatingImageToUltrasoundRegistrationFilter->SetSegmentation(segmentationNode, m_FloatingImage); + m_FloatingImageToUltrasoundRegistrationFilter->SetSurface(surfaceNode); + m_FloatingImageToUltrasoundRegistrationFilter + ->SetTransformMarkerCSToFloatingImageCS(m_TransformMarkerCSToFloatingImageCS); + m_FloatingImageToUltrasoundRegistrationFilter + ->SetTransformUSimageCSToTrackingCS(this->GetCombinedModality()->GetCalibration()); + m_FloatingImageToUltrasoundRegistrationFilter + ->ConnectTo(this->GetCombinedModality()->GetNavigationDataSource()); +} + +void QmitkUSNavigationStepCtUsRegistration::OnFreeze() +{ + if (this->GetCombinedModality(false).IsNull()) + { + return; + } + + if (!m_FreezeCombinedModality) + { + m_FreezeCombinedModality = true; + ui->freezeUnfreezePushButton->setText("Unfreeze"); + this->GetCombinedModality()->SetIsFreezed(true); + } + else + { + m_FreezeCombinedModality = false; + ui->freezeUnfreezePushButton->setText("Freeze"); + this->GetCombinedModality()->SetIsFreezed(false); + } +} + +void QmitkUSNavigationStepCtUsRegistration::OnActualizeSegmentationSurfacePointSetData() +{ + mitk::DataNode* segmentationNode = ui->segmentationComboBox->GetSelectedNode(); + if (segmentationNode == nullptr) + { + QMessageBox msgBox; + msgBox.setText("Cannot actualize segmentation + surface + pointset data. There is no segmentation selected."); + msgBox.exec(); + return; + } + + mitk::DataNode* surfaceNode = ui->selectedSurfaceComboBox->GetSelectedNode(); + if (surfaceNode == nullptr) + { + QMessageBox msgBox; + msgBox.setText("Cannot actualize segmentation + surface + pointset data. There is no surface selected."); + msgBox.exec(); + return; + } + + mitk::DataNode* pointSetNode = ui->pointSetComboBox->GetSelectedNode(); + if (pointSetNode == nullptr) + { + QMessageBox msgBox; + msgBox.setText("Cannot actualize segmentation + surface + pointset data. There is no pointSet selected."); + msgBox.exec(); + return; + } + + m_FloatingImageToUltrasoundRegistrationFilter->SetPointSet(pointSetNode); + m_FloatingImageToUltrasoundRegistrationFilter->SetSegmentation(segmentationNode, m_FloatingImage); + m_FloatingImageToUltrasoundRegistrationFilter->SetSurface(surfaceNode); +} + +void QmitkUSNavigationStepCtUsRegistration::OnGetCursorPosition() +{ + emit GetCursorPosition(); +} + +void QmitkUSNavigationStepCtUsRegistration::OnCalculateTRE(mitk::Point3D centroidOfTargetInUSImage) +{ + mitk::DataNode::Pointer pointSetNode = ui->pointSetComboBox->GetSelectedNode(); + if (pointSetNode.IsNull()) + { + QMessageBox msgBox; + msgBox.setText("Cannot calculate TRE. The pointSetComboBox node returned a nullptr."); + msgBox.exec(); + return; + } + + mitk::PointSet::Pointer pointSet = dynamic_cast(pointSetNode->GetData()); + if (pointSet.IsNull()) + { + ui->distanceTREValue->setText(QString("Unknown")); + return; + } + double distance = pointSet->GetPoint(0).EuclideanDistanceTo(centroidOfTargetInUSImage); + ui->distanceTREValue->setText(QString("%1").arg(distance)); +} + +void QmitkUSNavigationStepCtUsRegistration::OnCalculateCenter() +{ + mitk::DataNode::Pointer node = ui->segmentationComboBox->GetSelectedNode(); + if (node.IsNull()) + { + QMessageBox msgBox; + msgBox.setText("Cannot calculate the centroid of the segmentation."\ + "The segmentationComboBox node returned a nullptr."); + msgBox.exec(); + return; + } + + mitk::LabelSetImage::Pointer image = dynamic_cast(node->GetData()); + if (image.IsNull()) + { + MITK_WARN << "Cannot CalculateCenter - the segmentation cannot be converted to mitk::Image"; + return; + } + + ImageType::Pointer itkImage = ImageType::New(); + mitk::CastToItkImage(image, itkImage); + + //Initialize binary image to shape label map filter + BinaryImageToShapeLabelMapFilterType::Pointer shapeLabelMapFilter = BinaryImageToShapeLabelMapFilterType::New(); + shapeLabelMapFilter->SetInputForegroundValue(1); + + shapeLabelMapFilter->SetInput(itkImage); + shapeLabelMapFilter->Update(); + + BinaryImageToShapeLabelMapFilterType::OutputImageType::Pointer labelMap = + shapeLabelMapFilter->GetOutput(); + for (int i = labelMap->GetNumberOfLabelObjects() - 1; i >= 0; --i) + { + // Get the ith region + BinaryImageToShapeLabelMapFilterType::OutputImageType::LabelObjectType* labelObject = labelMap->GetNthLabelObject(i); + + mitk::Vector3D centroid; + centroid[0] = labelObject->GetCentroid()[0]; + centroid[1] = labelObject->GetCentroid()[1]; + centroid[2] = labelObject->GetCentroid()[2]; + MITK_INFO << "Centroid of segmentation = " << centroid; + } +} + +void QmitkUSNavigationStepCtUsRegistration::OnAddCtImageClicked() +{ + mitk::DataNode* selectedCtImage = ui->ctImagesToChooseComboBox->GetSelectedNode(); + if (selectedCtImage == nullptr) + { + return; + } + + mitk::Image::Pointer ctImage = dynamic_cast(selectedCtImage->GetData()); + if (ctImage.IsNull()) + { + MITK_WARN << "Failed to cast selected segmentation node to mitk::Image*"; + return; + } + QString name = QString::fromStdString(selectedCtImage->GetName()); + + for( int counter = 0; counter < ui->chosenCtImagesListWidget->count(); ++counter) + { + MITK_INFO << ui->chosenCtImagesListWidget->item(counter)->text() << " - " << counter; + MITK_INFO << m_ImagesGroundTruthProtocol.at(counter).GetPointer(); + if (ui->chosenCtImagesListWidget->item(counter)->text().compare(name) == 0) + { + MITK_INFO << "CT image already exist in list of chosen CT images. Do not add the image."; + return; + } + } + + ui->chosenCtImagesListWidget->addItem(name); + m_ImagesGroundTruthProtocol.push_back(ctImage); +} + +void QmitkUSNavigationStepCtUsRegistration::OnRemoveCtImageClicked() +{ + int position = ui->chosenCtImagesListWidget->currentRow(); + if (ui->chosenCtImagesListWidget->count() == 0 || position < 0) + { + return; + } + + m_ImagesGroundTruthProtocol.erase(m_ImagesGroundTruthProtocol.begin() + position); + QListWidgetItem *item = ui->chosenCtImagesListWidget->currentItem(); + ui->chosenCtImagesListWidget->removeItemWidget(item); + delete item; +} + +void QmitkUSNavigationStepCtUsRegistration::OnEvaluateGroundTruthFiducialLocalizationProtocol() +{ + m_GroundTruthProtocolFRE.clear(); + if (m_ImagesGroundTruthProtocol.size() != 6) + { + QMessageBox msgBox; + msgBox.setText("For evaluating the Ground-Truth-Fiducial-Localization-Protocol there must be loaded 6 different CT images."); + msgBox.exec(); + return; + } + + m_PerformingGroundTruthProtocolEvaluation = true; + this->CreatePointsToTransformForGroundTruthProtocol(); + m_GroundTruthProtocolTransformedPoints.clear(); + + for (unsigned int cycleNo = 0; cycleNo < m_ImagesGroundTruthProtocol.size(); ++cycleNo) + { + m_FloatingImage = m_ImagesGroundTruthProtocol.at(cycleNo); + this->SetFloatingImageGeometryInformation(m_FloatingImage.GetPointer()); + + this->OnLocalizeFiducials(); + this->OnRegisterMarkerToFloatingImageCS(); + this->TransformPointsGroundTruthProtocol(); + } + this->AddTransformedPointsToDataStorage(); + double meanFRE = this->CalculateMeanFRE(); + double sdOfFRE = this->CalculateStandardDeviationOfFRE(meanFRE); + this->CalculateGroundTruthProtocolTRE(); + + ui->meanFREValue->setText(QString("%1").arg(meanFRE)); + ui->sdFREValue->setText(QString("%1").arg(sdOfFRE)); + if (ui->protocolEvaluationTypeComboBox->currentText().compare("ANGLE") == 0) + { + if (m_GroundTruthProtocolTRE.find(0) != m_GroundTruthProtocolTRE.end()) + { + ui->TREValue->setText(QString("%1").arg(m_GroundTruthProtocolTRE.at(0))); + } + } + else if (ui->protocolEvaluationTypeComboBox->currentText().compare("PLANE") == 0) + { + if (m_GroundTruthProtocolTRE.find(0) != m_GroundTruthProtocolTRE.end() && + m_GroundTruthProtocolTRE.find(20) != m_GroundTruthProtocolTRE.end() && + m_GroundTruthProtocolTRE.find(40) != m_GroundTruthProtocolTRE.end() && + m_GroundTruthProtocolTRE.find(60) != m_GroundTruthProtocolTRE.end() && + m_GroundTruthProtocolTRE.find(80) != m_GroundTruthProtocolTRE.end() && + m_GroundTruthProtocolTRE.find(100) != m_GroundTruthProtocolTRE.end()) + { + ui->TREValue->setText(QString("Depth 0mm: %1\nDepth 20mm: %2\nDepth 40mm: %3\ + \nDepth 60mm: %4\nDepth 80mm: %5\nDepth 100mm: %6") + .arg(m_GroundTruthProtocolTRE.at(0)) + .arg(m_GroundTruthProtocolTRE.at(20)) + .arg(m_GroundTruthProtocolTRE.at(40)) + .arg(m_GroundTruthProtocolTRE.at(60)) + .arg(m_GroundTruthProtocolTRE.at(80)) + .arg(m_GroundTruthProtocolTRE.at(100))); + } + } + + m_PerformingGroundTruthProtocolEvaluation = false; +} diff --git a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.h new file mode 100644 index 0000000000..aa34b0edd0 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.h @@ -0,0 +1,237 @@ +/*=================================================================== + +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 QMITKUSNAVIGATIONSTEPCTUSREGISTRATION_H +#define QMITKUSNAVIGATIONSTEPCTUSREGISTRATION_H + +#include "QmitkUSAbstractNavigationStep.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include "itkVotingBinaryIterativeHoleFillingImageFilter.h" +#include + +namespace itk { +template class SmartPointer; + +} + +namespace mitk { +class NodeDisplacementFilter; +class NavigationDataSource; +class PlaneFit; +class FloatingImageToUltrasoundRegistrationFilter; +} + +namespace Ui { +class QmitkUSNavigationStepCtUsRegistration; +} + +// Declare typedefs: +typedef itk::Image ImageType; +typedef itk::ThresholdImageFilter ThresholdImageFilterType; +typedef itk::BinaryThresholdImageFilter BinaryThresholdImageFilterType; +typedef itk::LaplacianRecursiveGaussianImageFilter LaplacianRecursiveGaussianImageFilterType; +typedef itk::VotingBinaryIterativeHoleFillingImageFilter VotingBinaryIterativeHoleFillingImageFilterType; +typedef itk::BinaryImageToShapeLabelMapFilter BinaryImageToShapeLabelMapFilterType; +/** + * \brief Navigation step for marking risk structures. + * The user can add risk structures by interacting with the render windows. The + * risk structures are organized in an embedded table view. + * + * The risk structures are stored under DATANAME_BASENODE -> DATANAME_ZONES. + * + * This step is ready for the next step directly after activating. All actions + * to be done in this step are optional. + */ +class QmitkUSNavigationStepCtUsRegistration : public QmitkUSAbstractNavigationStep +{ + Q_OBJECT + +public: + explicit QmitkUSNavigationStepCtUsRegistration(QWidget *parent = 0); + ~QmitkUSNavigationStepCtUsRegistration(); + + /** + * \brief Initialization of the data storage nodes. + * \return always true + */ + virtual bool OnStartStep(); + + /** + * \brief Resets widget and filter and removes nodes from the data storage. + * \return always true + */ + virtual bool OnStopStep(); + + /** + * \brief There is nothing to be done. + * \return always true + */ + virtual bool OnFinishStep(); + + /** + * \brief Selects input for the node displacement filter and emits "ReadyForNextStep" signal. + * The input selection cannot be done earlier. + * \return + */ + virtual bool OnActivateStep(); + + virtual bool OnDeactivateStep(); + + /** + * \brief Updates the tracking validity status and the combined modality. + */ + virtual void OnUpdate(); + + /** + * The property "settings.interaction-concept" is used. + */ + virtual void OnSettingsChanged(const itk::SmartPointer settingsNode); + + virtual QString GetTitle(); + + /** + * @return a node displacement filter for the zone surfaces + */ + virtual FilterVector GetFilter(); + + void OnCalculateTRE(mitk::Point3D centroidOfTargetInUSImage); + +signals: + void ActualizeCtToUsRegistrationWidget(); + void GetCursorPosition(); + +protected: + virtual void OnSetCombinedModality(); + + void UnsetFloatingImageGeometry(); + void SetFloatingImageGeometryInformation(mitk::Image* image); + double GetVoxelVolume(); + double GetFiducialVolume(double radius); + + bool FilterFloatingImage(); + void InitializeImageFilters(); + + double GetCharacteristicDistanceAWithUpperMargin(); + double GetCharacteristicDistanceBWithLowerMargin(); + double GetCharacteristicDistanceBWithUpperMargin(); + double GetMinimalFiducialConfigurationDistance(); + void CreateMarkerModelCoordinateSystemPointSet(); + + //Methods for Ground-Truth-Fiducial-Localization-Protocol-Evaluation + void InitializePointsToTransformForGroundTruthProtocol(); + void CreatePointsToTransformForGroundTruthProtocol(); + void TransformPointsGroundTruthProtocol(); + void AddTransformedPointsToDataStorage(); + double CalculateMeanFRE(); + double CalculateStandardDeviationOfFRE(double meanFRE); + void CalculateGroundTruthProtocolTRE(); + // End methods Ground-Truth-Protocol + + void EliminateTooSmallLabeledObjects( ImageType::Pointer binaryImage); + bool EliminateFiducialCandidatesByEuclideanDistances(); + void ClassifyFiducialCandidates(); + void GetCentroidsOfLabeledObjects(); + void NumerateFiducialMarks(); + void CalculateDistancesBetweenFiducials(std::vector> &distanceVectorsFiducials); + bool FindFiducialNo1(std::vector> &distanceVectorsFiducials); + bool FindFiducialNo2And3(); + bool FindFiducialNo4(std::vector> &distanceVectorsFiducials); + bool FindFiducialNo5(); + bool FindFiducialNo6(); + bool FindFiducialNo7(); + bool FindFiducialNo8(); + void DefineDataStorageImageFilter(); + void CreateQtPartControl(QWidget *parent); + +protected slots: + void OnFloatingImageComboBoxSelectionChanged(const mitk::DataNode* node); + void OnRegisterMarkerToFloatingImageCS(); + void OnLocalizeFiducials(); + void OnVisualizeCTtoUSregistration(); + void OnFreeze(); + void OnActualizeSegmentationSurfacePointSetData(); + void OnGetCursorPosition(); + + void OnCalculateCenter(); + + //Methods for Ground-Truth-Fiducial-Localization-Protocol-Evaluation + void OnAddCtImageClicked(); + void OnRemoveCtImageClicked(); + void OnEvaluateGroundTruthFiducialLocalizationProtocol(); + +private: + Ui::QmitkUSNavigationStepCtUsRegistration *ui; + + mitk::NodePredicateAnd::Pointer m_IsOfTypeImagePredicate; + mitk::NodePredicateOr::Pointer m_IsASegmentationImagePredicate; + mitk::NodePredicateAnd::Pointer m_IsAPatientImagePredicate; + mitk::TNodePredicateDataType::Pointer m_IsAPointSetPredicate; + mitk::NodePredicateDataType::Pointer m_IsASurfacePredicate; + + itk::SmartPointer m_NavigationDataSource; + mitk::Image::Pointer m_FloatingImage; + mitk::PointSet::Pointer m_MarkerModelCoordinateSystemPointSet; + mitk::PointSet::Pointer m_MarkerFloatingImageCoordinateSystemPointSet; + + std::vector m_ImagesGroundTruthProtocol; + bool m_PerformingGroundTruthProtocolEvaluation; + std::vector m_GroundTruthProtocolFRE; + std::map m_GroundTruthProtocolTRE; + std::map m_PointsToTransformGroundTruthProtocol; + std::map m_GroundTruthProtocolTransformedPoints; + + ThresholdImageFilterType::Pointer m_ThresholdFilter; + BinaryThresholdImageFilterType::Pointer m_BinaryThresholdFilter; + LaplacianRecursiveGaussianImageFilterType::Pointer m_LaplacianFilter1; + LaplacianRecursiveGaussianImageFilterType::Pointer m_LaplacianFilter2; + VotingBinaryIterativeHoleFillingImageFilterType::Pointer m_HoleFillingFilter; + BinaryImageToShapeLabelMapFilterType::Pointer m_BinaryImageToShapeLabelMapFilter; + + itk::SmartPointer m_FloatingImageToUltrasoundRegistrationFilter; + + std::vector m_CentroidsOfFiducialCandidates; + std::map m_EigenVectorsFiducialCandidates; + std::vector m_EigenValuesFiducialCandidates; + mitk::Vector3D m_MeanCentroidFiducialCandidates; + std::map m_FiducialMarkerCentroids; + + mitk::AffineTransform3D::Pointer m_TransformMarkerCSToFloatingImageCS; + + /*! + \brief The 3D dimension of the CT image given in index size. + */ + mitk::Vector3D m_ImageDimension; + mitk::Vector3D m_ImageSpacing; + + bool m_FreezeCombinedModality; + mitk::Point3D m_CentroidOfTargetInUSImage; + +}; + +#endif // QMITKUSNAVIGATIONSTEPCTUSREGISTRATION_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.ui new file mode 100644 index 0000000000..fe3e112e7e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.ui @@ -0,0 +1,377 @@ + + + QmitkUSNavigationStepCtUsRegistration + + + + 0 + 0 + 403 + 933 + + + + Form + + + + + + Options + + + + + + 5mm Fiducial Diameter + + + true + + + + + + + 3mm Fiducial Diameter + + + false + + + + + + + Select Fiducial Marker Configuration + + + + + + + + 10mm Minimal Distance + + + + + 15mm Minimal Distance + + + + + 20mm Minimal Distance + + + + + + + + Use NDI-Tracker (if unchecked, Polhemus-Tracker is assumed to be used) + + + false + + + + + + + + + + Classic Way Of Registering Floating Image + + + + + + Selected Floating Image: + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Localize Fiducial Marker + + + + + + + Do Registration Marker CS -> Floating Image CS + + + + + + + Selected Segmentation(s): + + + + + + + + + + Selected Surface: + + + + + + + + + + Selected PointSet: + + + + + + + + + + Visualize CT-to-US-registration + + + + + + + Freeze + + + + + + + Actualize Segmentation + Surface + PointSet Data + + + + + + + Calculate TRE + + + + + + + Distance (TRE) between centroid of FloatingImage-target and + US-image target (in mm): + + + + + + + 0.000 + + + + + + + + + + Ground-Truth-Fiducial-Localization-Protocol + + + + + + + + + Chosen CT images: + + + + + + + 0 + + + + + + + + 0 + + + + + Add + + + + + + + Remove + + + + + + + + + + + 0 + + + + + Select Protocol-Evaluation-Type: + + + + + + + + PLANE + + + + + ANGLE + + + + + + + + + + Evaluate + + + + + + + QFormLayout::ExpandingFieldsGrow + + + 20 + + + 10 + + + 0 + + + + + Mean FRE (in mm): + + + + + + + 0 + + + + + + + Sd FRE (in mm): + + + + + + + 0 + + + + + + + TRE (in mm): + + + + + + + 0 + + + + + + + + + + + + Calculate Centroid Of Segmentation + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + QmitkDataStorageComboBox + QComboBox +
QmitkDataStorageComboBox.h
+
+
+ + + + +
diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.cpp similarity index 99% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.cpp index 8ad60d0537..93257aefb5 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.cpp @@ -1,1017 +1,1017 @@ /*=================================================================== 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 "QmitkUSNavigationStepMarkerIntervention.h" #include "ui_QmitkUSNavigationStepMarkerIntervention.h" #include "mitkBaseRenderer.h" #include "mitkContourModel.h" #include "mitkNeedleProjectionFilter.h" #include "mitkNodeDisplacementFilter.h" #include "mitkSurface.h" #include "mitkTextAnnotation2D.h" #include #include #include "../Filter/mitkUSNavigationTargetIntersectionFilter.h" #include "../Filter/mitkUSNavigationTargetOcclusionFilter.h" #include "../Filter/mitkUSNavigationTargetUpdateFilter.h" #include "../QmitkUSNavigationMarkerPlacement.h" #include "../Widgets/QmitkZoneProgressBar.h" #include "../mitkUSTargetPlacementQualityCalculator.h" #include "../Interactors/mitkUSPointMarkInteractor.h" #include "usModuleRegistry.h" #include "mitkLookupTable.h" #include "mitkLookupTableProperty.h" #include "mitkSurface.h" // VTK #include "vtkCellLocator.h" #include "vtkDataSet.h" #include "vtkDoubleArray.h" #include "vtkFloatArray.h" #include "vtkIdList.h" #include "vtkLinearTransform.h" #include "vtkLookupTable.h" #include "vtkMath.h" #include "vtkOBBTree.h" #include "vtkPointData.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkSelectEnclosedPoints.h" #include "vtkSmartPointer.h" #include #include "vtkTransformPolyDataFilter.h" #include "vtkWarpScalar.h" QmitkUSNavigationStepMarkerIntervention::QmitkUSNavigationStepMarkerIntervention(QWidget *parent) : QmitkUSAbstractNavigationStep(parent), m_NumberOfTargets(0), m_PlannedTargetsNodes(), m_ReachedTargetsNodes(), m_TargetProgressBar(new QmitkZoneProgressBar(QString::fromStdString("Target: %1 mm"), 200, 0, this)), m_PlannedTargetProgressBar(nullptr), m_CurrentTargetIndex(0), m_CurrentTargetReached(false), m_ShowPlanningColors(false), m_PointMarkInteractor(mitk::USPointMarkInteractor::New()), m_TargetNode(nullptr), m_TargetColorLookupTableProperty(nullptr), m_TargetSurface(nullptr), m_NeedleProjectionFilter(mitk::NeedleProjectionFilter::New()), m_NodeDisplacementFilter(mitk::NodeDisplacementFilter::New()), m_TargetUpdateFilter(mitk::USNavigationTargetUpdateFilter::New()), m_TargetOcclusionFilter(mitk::USNavigationTargetOcclusionFilter::New()), m_TargetIntersectionFilter(mitk::USNavigationTargetIntersectionFilter::New()), m_PlacementQualityCalculator(mitk::USTargetPlacementQualityCalculator::New()), m_TargetStructureWarnOverlay(mitk::TextAnnotation2D::New()), m_ReferenceSensorName(), m_NeedleSensorName(), m_ReferenceSensorIndex(1), m_NeedleSensorIndex(0), m_ListenerTargetCoordinatesChanged(this, &QmitkUSNavigationStepMarkerIntervention::UpdateTargetCoordinates), ui(new Ui::QmitkUSNavigationStepMarkerIntervention) { m_ActiveTargetColor[0] = 1; m_ActiveTargetColor[1] = 1; m_ActiveTargetColor[2] = 0; m_InactiveTargetColor[0] = 1; m_InactiveTargetColor[1] = 1; m_InactiveTargetColor[2] = 0.5; m_ReachedTargetColor[0] = 0.6; m_ReachedTargetColor[1] = 1; m_ReachedTargetColor[2] = 0.6; ui->setupUi(this); connect(ui->freezeImageButton, SIGNAL(SignalFreezed(bool)), this, SLOT(OnFreeze(bool))); connect(ui->backToLastTargetButton, SIGNAL(clicked()), this, SLOT(OnBackToLastTargetClicked())); connect(ui->targetReachedButton, SIGNAL(clicked()), this, SLOT(OnTargetLeft())); connect(this, SIGNAL(TargetReached(int)), this, SLOT(OnTargetReached())); connect(this, SIGNAL(TargetLeft(int)), this, SLOT(OnTargetLeft())); connect(ui->riskStructuresRangeWidget, SIGNAL(SignalZoneViolated(const mitk::DataNode *, mitk::Point3D)), this, SLOT(OnRiskZoneViolated(const mitk::DataNode *, mitk::Point3D))); m_PointMarkInteractor->CoordinatesChangedEvent.AddListener(m_ListenerTargetCoordinatesChanged); this->GenerateTargetColorLookupTable(); m_TargetProgressBar->SetTextFormatInvalid("Target is not on Needle Path"); ui->targetStructuresRangeLayout->addWidget(m_TargetProgressBar); m_TargetUpdateFilter->SetScalarArrayIdentifier("USNavigation::ReachedTargetScores"); } QmitkUSNavigationStepMarkerIntervention::~QmitkUSNavigationStepMarkerIntervention() { mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(false); if (dataStorage.IsNotNull()) { // remove the node for the needle path mitk::DataNode::Pointer node = this->GetNamedDerivedNode("Needle Path", QmitkUSAbstractNavigationStep::DATANAME_BASENODE); if (node.IsNotNull()) { dataStorage->Remove(node); } } delete ui; m_PointMarkInteractor->CoordinatesChangedEvent.RemoveListener(m_ListenerTargetCoordinatesChanged); } bool QmitkUSNavigationStepMarkerIntervention::OnStartStep() { m_NeedleProjectionFilter->SelectInput(m_NeedleSensorIndex); // create node for Needle Projection mitk::DataNode::Pointer node = this->GetNamedDerivedNodeAndCreate("Needle Path", QmitkUSAbstractNavigationStep::DATANAME_BASENODE); node->SetData(m_NeedleProjectionFilter->GetProjection()); node->SetBoolProperty("show contour", true); // initialize warning overlay (and do not display it, yet) m_TargetStructureWarnOverlay->SetText("Warning: Needle is Inside the Target Structure."); m_TargetStructureWarnOverlay->SetVisibility(false); // set position and font size for the text overlay mitk::Point2D overlayPosition; overlayPosition.SetElement(0, 10.0f); overlayPosition.SetElement(1, 10.0f); m_TargetStructureWarnOverlay->SetPosition2D(overlayPosition); m_TargetStructureWarnOverlay->SetFontSize(18); // overlay should be red mitk::Color color; color[0] = 1; color[1] = 0; color[2] = 0; m_TargetStructureWarnOverlay->SetColor(color); mitk::ManualPlacementAnnotationRenderer::AddAnnotation(m_TargetStructureWarnOverlay.GetPointer(), "stdmulti.widget4"); return true; } bool QmitkUSNavigationStepMarkerIntervention::OnStopStep() { mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(); // remove all reached nodes from the data storage for (QVector>::iterator it = m_ReachedTargetsNodes.begin(); it != m_ReachedTargetsNodes.end(); ++it) { dataStorage->Remove(*it); } m_ReachedTargetsNodes.clear(); m_CurrentTargetIndex = 0; // reset button states ui->freezeImageButton->setEnabled(false); ui->backToLastTargetButton->setEnabled(false); ui->targetReachedButton->setEnabled(true); // make sure that it is unfreezed after stopping the step ui->freezeImageButton->Unfreeze(); // remove base node for reached targets from the data storage mitk::DataNode::Pointer reachedTargetsNode = this->GetNamedDerivedNode( QmitkUSAbstractNavigationStep::DATANAME_BASENODE, QmitkUSNavigationMarkerPlacement::DATANAME_REACHED_TARGETS); if (reachedTargetsNode.IsNotNull()) { dataStorage->Remove(reachedTargetsNode); } return true; } bool QmitkUSNavigationStepMarkerIntervention::OnFinishStep() { return true; } bool QmitkUSNavigationStepMarkerIntervention::OnActivateStep() { this->ClearZones(); // clear risk zones before adding new ones // get target node from data storage and make sure that it contains data m_TargetNode = this->GetNamedDerivedNode(QmitkUSNavigationMarkerPlacement::DATANAME_TARGETSURFACE, - QmitkUSNavigationMarkerPlacement::DATANAME_TUMOUR); + QmitkUSNavigationMarkerPlacement::DATANAME_TUMOUR); if (m_TargetNode.IsNull() || m_TargetNode->GetData() == 0) { mitkThrow() << "Target node (" << QmitkUSNavigationMarkerPlacement::DATANAME_TARGETSURFACE << ") must not be null."; } // get target data and make sure that it is a surface m_TargetSurface = dynamic_cast(m_TargetNode->GetData()); if (m_TargetSurface.IsNull()) { mitkThrow() << "Target node (" << QmitkUSNavigationMarkerPlacement::DATANAME_TARGETSURFACE << ") data must be of type mitk::Surface"; } // delete progress bars for reinitializing them again afterwards if (m_PlannedTargetProgressBar) { ui->targetStructuresRangeLayout->removeWidget(m_PlannedTargetProgressBar); delete m_PlannedTargetProgressBar; m_PlannedTargetProgressBar = 0; } m_NodeDisplacementFilter->SelectInput(m_ReferenceSensorIndex); this->UpdateTargetProgressDisplay(); mitk::DataNode::Pointer tumourNode = this->GetNamedDerivedNode(QmitkUSNavigationMarkerPlacement::DATANAME_TUMOUR, QmitkUSAbstractNavigationStep::DATANAME_BASENODE); if (tumourNode.IsNotNull()) { // do not show tumour node during intervention (target surface is shown) tumourNode->SetBoolProperty("visible", false); // add tumour as a risk structure ui->riskStructuresRangeWidget->AddZone(tumourNode); } // set target structure for target update filter m_TargetUpdateFilter->SetTargetStructure(m_TargetNode); m_TargetOcclusionFilter->SetTargetStructure(m_TargetNode); // set lookup table of tumour node m_TargetNode->SetProperty("LookupTable", m_TargetColorLookupTableProperty); // mitk::DataNode::Pointer targetsBaseNode = this->GetNamedDerivedNode(QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS, QmitkUSAbstractNavigationStep::DATANAME_BASENODE); mitk::DataStorage::SetOfObjects::ConstPointer plannedTargetNodes; if (targetsBaseNode.IsNotNull()) { plannedTargetNodes = this->GetDataStorage()->GetDerivations(targetsBaseNode); } if (plannedTargetNodes.IsNotNull() && plannedTargetNodes->Size() > 0) { for (mitk::DataStorage::SetOfObjects::ConstIterator it = plannedTargetNodes->Begin(); it != plannedTargetNodes->End(); ++it) { m_PlannedTargetsNodes.push_back(it->Value()); } m_PlannedTargetProgressBar = new QmitkZoneProgressBar(QString::fromStdString("Planned Target"), 200, 0); ui->targetStructuresRangeLayout->addWidget(m_PlannedTargetProgressBar); } // add progress bars for risk zone nodes mitk::DataNode::Pointer zonesBaseNode = this->GetNamedDerivedNode(QmitkUSNavigationMarkerPlacement::DATANAME_ZONES, QmitkUSAbstractNavigationStep::DATANAME_BASENODE); // only add progress bars if the base node for zones was created if (zonesBaseNode.IsNotNull()) { mitk::DataStorage::SetOfObjects::ConstPointer zoneNodes = this->GetDataStorage()->GetDerivations(zonesBaseNode); for (mitk::DataStorage::SetOfObjects::ConstIterator it = zoneNodes->Begin(); it != zoneNodes->End(); ++it) { ui->riskStructuresRangeWidget->AddZone(it->Value()); } m_TargetOcclusionFilter->SelectStartPositionInput(m_NeedleSensorIndex); m_TargetOcclusionFilter->SetObstacleStructures(zoneNodes); } return true; } bool QmitkUSNavigationStepMarkerIntervention::OnDeactivateStep() { ui->freezeImageButton->Unfreeze(); return true; } void QmitkUSNavigationStepMarkerIntervention::OnUpdate() { // get navigation data source and make sure that it is not null mitk::NavigationDataSource::Pointer navigationDataSource = this->GetCombinedModality()->GetNavigationDataSource(); if (navigationDataSource.IsNull()) { MITK_ERROR("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepMarkerIntervention") << "Navigation Data Source of Combined Modality must not be null."; mitkThrow() << "Navigation Data Source of Combined Modality must not be null."; } ui->riskStructuresRangeWidget->UpdateDistancesToNeedlePosition(navigationDataSource->GetOutput(m_NeedleSensorIndex)); this->UpdateBodyMarkerStatus(navigationDataSource->GetOutput(m_ReferenceSensorIndex)); this->UpdateTargetColors(); this->UpdateTargetScore(); this->UpdateTargetViolationStatus(); } void QmitkUSNavigationStepMarkerIntervention::OnSettingsChanged(const itk::SmartPointer settingsNode) { if (settingsNode.IsNull()) { return; } int numberOfTargets; if (settingsNode->GetIntProperty("settings.number-of-targets", numberOfTargets)) { m_NumberOfTargets = numberOfTargets; m_TargetUpdateFilter->SetNumberOfTargets(numberOfTargets); m_PlacementQualityCalculator->SetOptimalAngle(m_TargetUpdateFilter->GetOptimalAngle()); } std::string referenceSensorName; if (settingsNode->GetStringProperty("settings.reference-name-selected", referenceSensorName)) { m_ReferenceSensorName = referenceSensorName; } std::string needleSensorName; if (settingsNode->GetStringProperty("settings.needle-name-selected", needleSensorName)) { m_NeedleSensorName = needleSensorName; } this->UpdateSensorsNames(); } QString QmitkUSNavigationStepMarkerIntervention::GetTitle() { return "Computer-assisted Intervention"; } bool QmitkUSNavigationStepMarkerIntervention::GetIsRestartable() { return true; } QmitkUSAbstractNavigationStep::FilterVector QmitkUSNavigationStepMarkerIntervention::GetFilter() { FilterVector filter; filter.push_back(m_NeedleProjectionFilter.GetPointer()); filter.push_back(m_NodeDisplacementFilter.GetPointer()); filter.push_back(m_TargetOcclusionFilter.GetPointer()); return filter; } void QmitkUSNavigationStepMarkerIntervention::OnSetCombinedModality() { - mitk::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(false); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(false); if (combinedModality.IsNotNull()) { mitk::AffineTransform3D::Pointer calibration = combinedModality->GetCalibration(); if (calibration.IsNotNull()) { m_NeedleProjectionFilter->SetTargetPlane(calibration); } } ui->freezeImageButton->SetCombinedModality(combinedModality, m_ReferenceSensorIndex); this->UpdateSensorsNames(); } void QmitkUSNavigationStepMarkerIntervention::OnTargetReached() { m_CurrentTargetReached = true; } void QmitkUSNavigationStepMarkerIntervention::OnTargetLeft() { m_CurrentTargetReached = false; m_CurrentTargetIndex++; if (m_CurrentTargetIndex >= 0 && static_cast(m_CurrentTargetIndex) >= m_NumberOfTargets) { ui->targetReachedButton->setDisabled(true); } ui->backToLastTargetButton->setEnabled(true); ui->freezeImageButton->setEnabled(true); this->UpdateTargetProgressDisplay(); if (m_ReachedTargetsNodes.size() < m_CurrentTargetIndex) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetName( (QString("Target ") + QString("%1").arg(m_CurrentTargetIndex, 2, 10, QLatin1Char('0'))).toStdString()); this->GetDataStorage()->Add( node, this->GetNamedDerivedNodeAndCreate(QmitkUSNavigationMarkerPlacement::DATANAME_REACHED_TARGETS, QmitkUSAbstractNavigationStep::DATANAME_BASENODE)); m_ReachedTargetsNodes.push_back(node); } mitk::DataNode::Pointer node = m_ReachedTargetsNodes.at(m_CurrentTargetIndex - 1); mitk::Surface::Pointer zone = mitk::Surface::New(); // create a vtk sphere with given radius vtkSmartPointer vtkSphere = vtkSmartPointer::New(); vtkSphere->SetRadius(5); vtkSphere->SetCenter(0, 0, 0); vtkSphere->Update(); zone->SetVtkPolyData(vtkSphere->GetOutput()); // set vtk sphere and origin to data node node->SetData(zone); node->GetData()->GetGeometry()->SetOrigin( this->GetCombinedModality()->GetNavigationDataSource()->GetOutput(m_NeedleSensorIndex)->GetPosition()); node->SetColor(0.2, 0.9, 0.2); this->UpdateTargetCoordinates(node); } void QmitkUSNavigationStepMarkerIntervention::OnBackToLastTargetClicked() { if (m_CurrentTargetIndex < 1) { MITK_WARN << "Cannot go back to last target as there is no last target."; return; } m_CurrentTargetIndex--; if (m_ReachedTargetsNodes.size() > m_CurrentTargetIndex) { this->GetDataStorage()->Remove(m_ReachedTargetsNodes.last()); MITK_INFO("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepMarkerIntervention") << "Removed Target " << m_ReachedTargetsNodes.size(); m_ReachedTargetsNodes.pop_back(); } if (m_CurrentTargetIndex == 0) { ui->backToLastTargetButton->setDisabled(true); } if (m_CurrentTargetIndex >= 0 && static_cast(m_CurrentTargetIndex) < m_NumberOfTargets) { ui->targetReachedButton->setEnabled(true); } ui->freezeImageButton->setEnabled(false); ui->freezeImageButton->Unfreeze(); this->UpdateTargetProgressDisplay(); m_TargetUpdateFilter->RemovePositionOfTarget(m_CurrentTargetIndex); } void QmitkUSNavigationStepMarkerIntervention::OnFreeze(bool freezed) { if (freezed) { this->GetCombinedModality()->SetIsFreezed(true); // load state machine and event config for data interactor m_PointMarkInteractor->LoadStateMachine("USPointMarkInteractions.xml", us::ModuleRegistry::GetModule("MitkUS")); m_PointMarkInteractor->SetEventConfig("globalConfig.xml"); if (m_CurrentTargetIndex < 1) { mitkThrow() << "Current target index has to be greater zero when freeze button is clicked."; } if (m_ReachedTargetsNodes.size() < m_CurrentTargetIndex) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetName( (QString("Target ") + QString("%1").arg(m_CurrentTargetIndex, 2, 10, QLatin1Char('0'))).toStdString()); this->GetDataStorage()->Add( node, this->GetNamedDerivedNodeAndCreate(QmitkUSNavigationMarkerPlacement::DATANAME_REACHED_TARGETS, QmitkUSAbstractNavigationStep::DATANAME_BASENODE)); m_ReachedTargetsNodes.push_back(node); } m_PointMarkInteractor->SetDataNode(m_ReachedTargetsNodes.last()); } else { m_PointMarkInteractor->SetDataNode(0); this->GetCombinedModality()->SetIsFreezed(false); } } void QmitkUSNavigationStepMarkerIntervention::OnShowPlanningView(bool show) { m_ShowPlanningColors = show; } void QmitkUSNavigationStepMarkerIntervention::OnRiskZoneViolated(const mitk::DataNode *node, mitk::Point3D position) { MITK_INFO << "Risk zone (" << node->GetName() << ") violated at position " << position << "."; } void QmitkUSNavigationStepMarkerIntervention::ClearZones() { ui->riskStructuresRangeWidget->ClearZones(); // remove all reached target nodes from the data storage and clear the list mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(); for (QVector::iterator it = m_ReachedTargetsNodes.begin(); it != m_ReachedTargetsNodes.end(); ++it) { if (it->IsNotNull()) { dataStorage->Remove(*it); } } m_ReachedTargetsNodes.clear(); } void QmitkUSNavigationStepMarkerIntervention::UpdateTargetCoordinates(mitk::DataNode *dataNode) { m_NodeDisplacementFilter->ResetNodes(); for (QVector>::iterator it = m_ReachedTargetsNodes.begin(); it != m_ReachedTargetsNodes.end(); ++it) { if (it->IsNotNull() && (*it)->GetData() != 0) { m_NodeDisplacementFilter->AddNode(*it); } } mitk::BaseData *baseData = dataNode->GetData(); if (!baseData) { mitkThrow() << "Data of the data node must not be null."; } mitk::BaseGeometry::Pointer geometry = baseData->GetGeometry(); if (geometry.IsNull()) { mitkThrow() << "Geometry of the data node must not be null."; } m_TargetUpdateFilter->SetControlNode(m_CurrentTargetIndex - 1, dataNode); if (m_PlannedTargetsNodes.size() > m_CurrentTargetIndex - 1) { m_PlannedTargetsNodes.at(m_CurrentTargetIndex - 1)->SetVisibility(false); } MITK_INFO("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepMarkerIntervention") << "Target " << m_CurrentTargetIndex << " reached at position " << geometry->GetOrigin(); this->CalculateTargetPlacementQuality(); } void QmitkUSNavigationStepMarkerIntervention::UpdateBodyMarkerStatus(mitk::NavigationData::Pointer bodyMarker) { if (bodyMarker.IsNull()) { MITK_ERROR("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepMarkerIntervention") << "Current Navigation Data for body marker of Combined Modality must not be null."; mitkThrow() << "Current Navigation Data for body marker of Combined Modality must not be null."; } bool valid = bodyMarker->IsDataValid(); // update body marker status label if (valid) { ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #8bff8b; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); ui->bodyMarkerTrackingStatusLabel->setText("Body marker is inside the tracking volume."); } else { ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #ff7878; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); ui->bodyMarkerTrackingStatusLabel->setText("Body marker is not inside the tracking volume."); } ui->targetStructuresRangeGroupBox->setEnabled(valid); ui->riskStructuresRangeGroupBox->setEnabled(valid); } void QmitkUSNavigationStepMarkerIntervention::GenerateTargetColorLookupTable() { vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetHueRange(0.0, 0.33); lookupTable->SetSaturationRange(1.0, 1.0); lookupTable->SetValueRange(1.0, 1.0); lookupTable->SetTableRange(0.0, 1.0); lookupTable->Build(); mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); lut->SetVtkLookupTable(lookupTable); m_TargetColorLookupTableProperty = mitk::LookupTableProperty::New(lut); } void QmitkUSNavigationStepMarkerIntervention::UpdateTargetColors() { if (m_TargetNode.IsNull()) { return; } m_TargetNode->SetColor(1, 1, 1); mitk::BaseData *targetNodeData = m_TargetNode->GetData(); if (targetNodeData == 0) { return; } mitk::Surface::Pointer targetNodeSurface = dynamic_cast(targetNodeData); vtkSmartPointer targetNodeSurfaceVtk = targetNodeSurface->GetVtkPolyData(); vtkPointData *targetPointData = targetNodeSurface->GetVtkPolyData()->GetPointData(); vtkFloatArray *scalars = dynamic_cast(targetPointData->GetScalars("USNavigation::Occlusion")); vtkFloatArray *targetScoreScalars; if (m_ShowPlanningColors) { targetScoreScalars = dynamic_cast(targetPointData->GetScalars("USNavigation::PlanningScalars")); } else { targetScoreScalars = dynamic_cast(targetPointData->GetScalars("USNavigation::ReachedTargetScores")); } if (!scalars || !targetScoreScalars) { return; } unsigned int numberOfTupels = scalars->GetNumberOfTuples(); vtkSmartPointer colors = vtkSmartPointer::New(); colors->SetNumberOfComponents(1); colors->SetNumberOfTuples(numberOfTupels); colors->SetName("Colors"); double color, intersection, markerScore; for (unsigned int n = 0; n < numberOfTupels; n++) { scalars->GetTuple(n, &intersection); targetScoreScalars->GetTuple(n, &markerScore); if (intersection > 0) { color = 0; } else { color = markerScore; } colors->SetTuple(n, &color); } if (numberOfTupels > 0) { targetNodeSurfaceVtk->GetPointData()->SetScalars(colors); targetNodeSurfaceVtk->GetPointData()->Update(); } } void QmitkUSNavigationStepMarkerIntervention::UpdateTargetScore() { if (m_NeedleProjectionFilter->GetProjection()->GetSize() != 2) { return; } vtkSmartPointer targetSurfaceVtk = m_TargetSurface->GetVtkPolyData(); m_TargetIntersectionFilter->SetTargetSurface(m_TargetSurface); m_TargetIntersectionFilter->SetLine(m_NeedleProjectionFilter->GetProjection()); m_TargetIntersectionFilter->CalculateIntersection(); if (m_TargetIntersectionFilter->GetIsIntersecting()) { vtkFloatArray *scalars = dynamic_cast(targetSurfaceVtk->GetPointData()->GetScalars("USNavigation::ReachedTargetScores")); double score; scalars->GetTuple(m_TargetIntersectionFilter->GetIntersectionNearestSurfacePointId(), &score); double color[3]; m_TargetColorLookupTableProperty->GetLookupTable()->GetVtkLookupTable()->GetColor(score, color); float colorF[3]; colorF[0] = color[0]; colorF[1] = color[1]; colorF[2] = color[2]; m_TargetProgressBar->SetColor(colorF); m_TargetProgressBar->SetBorderColor(colorF); m_TargetProgressBar->setValue(m_TargetIntersectionFilter->GetDistanceToIntersection()); if (m_PlannedTargetProgressBar) { vtkFloatArray *scalars = dynamic_cast(targetSurfaceVtk->GetPointData()->GetScalars("USNavigation::PlanningScalars")); if (scalars) { double score; scalars->GetTuple(m_TargetIntersectionFilter->GetIntersectionNearestSurfacePointId(), &score); double color[3]; m_TargetColorLookupTableProperty->GetLookupTable()->GetVtkLookupTable()->GetColor(score, color); float colorF[3]; colorF[0] = color[0]; colorF[1] = color[1]; colorF[2] = color[2]; m_PlannedTargetProgressBar->SetColor(colorF); m_PlannedTargetProgressBar->SetBorderColor(colorF); m_PlannedTargetProgressBar->SetTextFormatValid("Planned Target: %1 mm"); mitk::Point3D intersectionPoint = m_TargetIntersectionFilter->GetIntersectionPoint(); mitk::ScalarType minDistance = -1; for (QVector>::iterator it = m_PlannedTargetsNodes.begin(); it != m_PlannedTargetsNodes.end(); ++it) { mitk::ScalarType distance = intersectionPoint.EuclideanDistanceTo((*it)->GetData()->GetGeometry()->GetOrigin()); if (minDistance < 0 || distance < minDistance) { minDistance = distance; } } m_PlannedTargetProgressBar->setValue(minDistance); } } } else { m_TargetProgressBar->setValueInvalid(); } } void QmitkUSNavigationStepMarkerIntervention::UpdateTargetProgressDisplay() { QString description; if (m_CurrentTargetIndex >= static_cast(m_NumberOfTargets)) { description = "All Targets Reached"; if (m_TargetProgressBar) { m_TargetProgressBar->hide(); } } else { description = QString("Distance to Target ") + QString::number(m_CurrentTargetIndex + 1) + QString(" of ") + QString::number(m_NumberOfTargets); if (m_TargetProgressBar) { m_TargetProgressBar->show(); } } ui->targetStructuresRangeGroupBox->setTitle(description); } void QmitkUSNavigationStepMarkerIntervention::UpdatePlannedTargetProgressDisplay() { // make sure that the needle projection consists of two points if (m_NeedleProjectionFilter->GetProjection()->GetSize() != 2) { return; } vtkSmartPointer targetSurfaceVtk = m_TargetSurface->GetVtkPolyData(); m_TargetIntersectionFilter->SetTargetSurface(m_TargetSurface); m_TargetIntersectionFilter->SetLine(m_NeedleProjectionFilter->GetProjection()); m_TargetIntersectionFilter->CalculateIntersection(); // update target progress bar according to the color of the intersection // point on the target surface and the distance to the intersection if (m_TargetIntersectionFilter->GetIsIntersecting()) { vtkFloatArray *scalars = dynamic_cast(targetSurfaceVtk->GetPointData()->GetScalars("Colors")); double score; scalars->GetTuple(m_TargetIntersectionFilter->GetIntersectionNearestSurfacePointId(), &score); double color[3]; m_TargetColorLookupTableProperty->GetLookupTable()->GetVtkLookupTable()->GetColor(score, color); float colorF[3]; colorF[0] = color[0]; colorF[1] = color[1]; colorF[2] = color[2]; m_TargetProgressBar->SetColor(colorF); m_TargetProgressBar->SetBorderColor(colorF); m_TargetProgressBar->setValue(m_TargetIntersectionFilter->GetDistanceToIntersection()); } else { float red[3] = {0.6f, 0.0f, 0.0f}; m_TargetProgressBar->SetBorderColor(red); m_TargetProgressBar->setValueInvalid(); } } void QmitkUSNavigationStepMarkerIntervention::UpdateTargetViolationStatus() { // transform vtk polydata according to mitk geometry vtkSmartPointer transformFilter = vtkSmartPointer::New(); transformFilter->SetInputData(0, m_TargetSurface->GetVtkPolyData()); transformFilter->SetTransform(m_TargetSurface->GetGeometry()->GetVtkTransform()); transformFilter->Update(); vtkSmartPointer enclosedPoints = vtkSmartPointer::New(); enclosedPoints->Initialize(transformFilter->GetOutput()); mitk::Point3D needleTip = m_NeedleProjectionFilter->GetProjection()->GetPoint(0); // show warning if the needle tip is inside the target surface if (enclosedPoints->IsInsideSurface(needleTip[0], needleTip[1], needleTip[2])) { if (!m_TargetStructureWarnOverlay->IsVisible(NULL)) { m_TargetStructureWarnOverlay->SetVisibility(true); mitk::DataNode::Pointer targetViolationResult = mitk::DataNode::New(); targetViolationResult->SetName("TargetViolation"); targetViolationResult->SetProperty("USNavigation::TargetViolationPoint", mitk::Point3dProperty::New(needleTip)); emit SignalIntermediateResult(targetViolationResult); } MITK_INFO("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepMarkerIntervention") << "Target surface violated at " << needleTip << "."; } else { m_TargetStructureWarnOverlay->SetVisibility(false); } } void QmitkUSNavigationStepMarkerIntervention::CalculateTargetPlacementQuality() { // clear quality display if there aren't all targets reached if (m_ReachedTargetsNodes.size() != static_cast(m_NumberOfTargets)) { ui->placementQualityGroupBox->setEnabled(false); ui->angleDifferenceValue->setText(""); ui->centersOfMassValue->setText(""); return; } ui->placementQualityGroupBox->setEnabled(true); mitk::Surface::Pointer targetSurface = dynamic_cast(m_TargetNode->GetData()); if (targetSurface.IsNull()) { mitkThrow() << "Target surface must not be null."; } m_PlacementQualityCalculator->SetTargetSurface(targetSurface); mitk::PointSet::Pointer targetPointSet = mitk::PointSet::New(); // copy the origins of all reached target nodes into a point set // for the quality calculator mitk::PointSet::PointIdentifier n = 0; for (QVector>::iterator it = m_ReachedTargetsNodes.begin(); it != m_ReachedTargetsNodes.end(); ++it) { targetPointSet->InsertPoint(n++, (*it)->GetData()->GetGeometry()->GetOrigin()); } m_PlacementQualityCalculator->SetTargetPoints(targetPointSet); m_PlacementQualityCalculator->Update(); double centersOfMassDistance = m_PlacementQualityCalculator->GetCentersOfMassDistance(); ui->centersOfMassValue->setText(QString::number(centersOfMassDistance, 103, 2) + " mm"); double meanAnglesDifference = m_PlacementQualityCalculator->GetMeanAngleDifference(); ui->angleDifferenceValue->setText(QString::number(meanAnglesDifference, 103, 2) + QString::fromLatin1(" °")); // create an intermediate result of the placement quality mitk::DataNode::Pointer placementQualityResult = mitk::DataNode::New(); placementQualityResult->SetName("PlacementQuality"); placementQualityResult->SetFloatProperty("USNavigation::CentersOfMassDistance", centersOfMassDistance); placementQualityResult->SetFloatProperty("USNavigation::MeanAngleDifference", meanAnglesDifference); placementQualityResult->SetProperty( "USNavigation::AngleDifferences", mitk::GenericProperty::New(m_PlacementQualityCalculator->GetAngleDifferences())); if (m_PlannedTargetsNodes.size() == static_cast(m_NumberOfTargets)) { mitk::VnlVector reachedPlannedDifferences; double reachedPlannedDifferencesSum = 0; double reachedPlannedDifferencesMax = 0; reachedPlannedDifferences.set_size(m_NumberOfTargets); // get sum and maximum of the planning / reality differences for (unsigned int n = 0; n < m_NumberOfTargets; ++n) { mitk::ScalarType distance = m_PlannedTargetsNodes.at(n)->GetData()->GetGeometry()->GetOrigin().EuclideanDistanceTo( m_ReachedTargetsNodes.at(n)->GetData()->GetGeometry()->GetOrigin()); reachedPlannedDifferences.put(n, distance); reachedPlannedDifferencesSum += distance; if (distance > reachedPlannedDifferencesMax) { reachedPlannedDifferencesMax = distance; } } // add distances between planning and reality to the quality intermediate result placementQualityResult->SetProperty("USNavigation::PlanningRealityDistances", mitk::GenericProperty::New(reachedPlannedDifferences)); placementQualityResult->SetProperty( "USNavigation::MeanPlanningRealityDistance", mitk::DoubleProperty::New(reachedPlannedDifferencesSum / static_cast(m_NumberOfTargets))); placementQualityResult->SetProperty("USNavigation::MaximumPlanningRealityDistance", mitk::DoubleProperty::New(reachedPlannedDifferencesMax)); } emit SignalIntermediateResult(placementQualityResult); } void QmitkUSNavigationStepMarkerIntervention::UpdateSensorsNames() { - mitk::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(false); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(false); if (combinedModality.IsNull()) { return; } mitk::NavigationDataSource::Pointer navigationDataSource = combinedModality->GetNavigationDataSource(); if (navigationDataSource.IsNull()) { return; } if (!m_NeedleSensorName.empty()) { try { m_NeedleSensorIndex = navigationDataSource->GetOutputIndex(m_NeedleSensorName); } catch (const std::exception &e) { MITK_WARN("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepPlacementPlanning") << "Cannot get index for needle sensor name: " << e.what(); } } if (this->GetNavigationStepState() >= QmitkUSAbstractNavigationStep::State_Active) { m_NeedleProjectionFilter->SelectInput(m_NeedleSensorIndex); } if (!m_ReferenceSensorName.empty()) { try { m_ReferenceSensorIndex = navigationDataSource->GetOutputIndex(m_ReferenceSensorName); } catch (const std::exception &e) { MITK_WARN("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepPlacementPlanning") << "Cannot get index for reference sensor name: " << e.what(); } } if (this->GetNavigationStepState() >= QmitkUSAbstractNavigationStep::State_Active) { m_NodeDisplacementFilter->SelectInput(m_ReferenceSensorIndex); } ui->freezeImageButton->SetCombinedModality(combinedModality, m_ReferenceSensorIndex); } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.ui similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.ui diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.cpp similarity index 99% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.cpp index b86f9595d3..16b74da2d9 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.cpp @@ -1,816 +1,816 @@ /*=================================================================== 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 "QmitkUSNavigationStepPlacementPlanning.h" #include "ui_QmitkUSNavigationStepPlacementPlanning.h" #include "../Interactors/mitkUSPointMarkInteractor.h" #include "../mitkUSTargetPlacementQualityCalculator.h" #include "mitkNeedleProjectionFilter.h" #include "mitkNodeDisplacementFilter.h" #include "usModuleRegistry.h" #include "../Filter/mitkUSNavigationTargetIntersectionFilter.h" #include "../Filter/mitkUSNavigationTargetUpdateFilter.h" #include "../QmitkUSNavigationMarkerPlacement.h" #include "mitkLookupTableProperty.h" #include "mitkSurface.h" #include #include "mitkLayoutAnnotationRenderer.h" #include "mitkTextAnnotation3D.h" #include "vtkFloatArray.h" #include "vtkLookupTable.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkSmartPointer.h" #include "vtkLineSource.h" #include #include "vtkCenterOfMass.h" #include "vtkLinearTransform.h" #include "vtkPoints.h" #include "vtkTransformPolyDataFilter.h" #include "vtkUnstructuredGrid.h" #include "vtkMath.h" QmitkUSNavigationStepPlacementPlanning::QmitkUSNavigationStepPlacementPlanning(QWidget *parent) : QmitkUSAbstractNavigationStep(parent), m_NumberOfTargets(0), m_CurrentTargetIndex(0), m_BodyMarkerValid(false), m_PointMarkInteractor(mitk::USPointMarkInteractor::New()), m_TargetUpdateFilter(mitk::USNavigationTargetUpdateFilter::New()), m_NodeDisplacementFilter(mitk::NodeDisplacementFilter::New()), m_NeedleProjectionFilter(mitk::NeedleProjectionFilter::New()), m_TargetIntersectionFilter(mitk::USNavigationTargetIntersectionFilter::New()), m_PlacementQualityCalculator(mitk::USTargetPlacementQualityCalculator::New()), m_ReferenceSensorIndex(1), m_NeedleSensorIndex(0), m_ListenerTargetCoordinatesChanged(this, &QmitkUSNavigationStepPlacementPlanning::UpdateTargetCoordinates), ui(new Ui::QmitkUSNavigationStepPlacementPlanning) { ui->setupUi(this); connect(ui->freezeImageButton, SIGNAL(SignalFreezed(bool)), this, SLOT(OnFreeze(bool))); m_TargetUpdateFilter->SetScalarArrayIdentifier("USNavigation::PlanningPlacement"); this->GenerateTargetColorLookupTable(); } QmitkUSNavigationStepPlacementPlanning::~QmitkUSNavigationStepPlacementPlanning() { delete ui; } bool QmitkUSNavigationStepPlacementPlanning::OnStartStep() { // create node for needle projection mitk::DataNode::Pointer node = this->GetNamedDerivedNodeAndCreate("Needle Path", QmitkUSAbstractNavigationStep::DATANAME_BASENODE); node->SetData(m_NeedleProjectionFilter->GetProjection()); node->SetBoolProperty("show contour", true); // make sure that the targets node exist in the data storage this->GetNamedDerivedNodeAndCreate(QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS, QmitkUSAbstractNavigationStep::DATANAME_BASENODE); this->GetNamedDerivedNodeAndCreate(QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS_PATHS, QmitkUSAbstractNavigationStep::DATANAME_BASENODE); // listen to event of point mark interactor m_PointMarkInteractor->CoordinatesChangedEvent.AddListener(m_ListenerTargetCoordinatesChanged); return true; } bool QmitkUSNavigationStepPlacementPlanning::OnStopStep() { // remove listener to event of point mark interactor m_PointMarkInteractor->CoordinatesChangedEvent.RemoveListener(m_ListenerTargetCoordinatesChanged); m_CurrentTargetIndex = 0; m_TargetUpdateFilter->Reset(); m_NodeDisplacementFilter->ResetNodes(); // remove the planned target nodes from the data storage mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(); for (QVector>::iterator it = m_PlannedTargetNodes.begin(); it != m_PlannedTargetNodes.end(); ++it) { dataStorage->Remove(*it); } m_PlannedTargetNodes.clear(); // remove the planned target path nodes from the data storage for (QVector>::iterator it = m_PlannedNeedlePaths.begin(); it != m_PlannedNeedlePaths.end(); ++it) { dataStorage->Remove(*it); } m_PlannedNeedlePaths.clear(); // remove the targets node from the data storage mitk::DataNode::Pointer targetsNode = this->GetNamedDerivedNode(QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS, QmitkUSAbstractNavigationStep::DATANAME_BASENODE); if (targetsNode.IsNotNull()) { dataStorage->Remove(targetsNode); } // remove the target paths node from the data storage mitk::DataNode::Pointer targetPathsNode = this->GetNamedDerivedNode( QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS_PATHS, QmitkUSAbstractNavigationStep::DATANAME_BASENODE); if (targetPathsNode.IsNotNull()) { dataStorage->Remove(targetPathsNode); } // make sure that the image is no longer freezed after stopping ui->freezeImageButton->Unfreeze(); return true; } bool QmitkUSNavigationStepPlacementPlanning::OnRestartStep() { this->OnStopStep(); this->OnStartStep(); return true; } bool QmitkUSNavigationStepPlacementPlanning::OnFinishStep() { // create scalars showing the planned positions on the target surface if (!m_PlannedTargetNodes.isEmpty()) { mitk::USNavigationTargetUpdateFilter::Pointer planningSurfaceFilter = mitk::USNavigationTargetUpdateFilter::New(); planningSurfaceFilter->SetOptimalAngle(0); planningSurfaceFilter->SetScalarArrayIdentifier("USNavigation::PlanningScalars"); planningSurfaceFilter->SetUseMaximumScore(true); planningSurfaceFilter->SetTargetStructure(m_TargetNode); unsigned int n = 0; for (QVector>::iterator it = m_PlannedTargetNodes.begin(); it != m_PlannedTargetNodes.end(); ++it) { bool isSurfaceEmpty; if (((*it)->GetBoolProperty("surface_empty", isSurfaceEmpty)) && isSurfaceEmpty) { // remove node from data storage if it is not fully planned this->GetDataStorage()->Remove(*it); } else { // set origin to filter for coloring target surface (good // positions are positions near to the origin) planningSurfaceFilter->SetControlNode(n, *it); } n++; } } // make sure that the image is no longer freezed after finishing ui->freezeImageButton->Unfreeze(); return true; } bool QmitkUSNavigationStepPlacementPlanning::OnActivateStep() { emit SignalReadyForNextStep(); m_NodeDisplacementFilter->SelectInput(m_ReferenceSensorIndex); m_NeedleProjectionFilter->SelectInput(m_NeedleSensorIndex); if (m_PlannedTargetNodes.empty()) { m_CurrentTargetIndex = 0; } else { m_CurrentTargetIndex = m_PlannedTargetNodes.size() - 1; } m_TargetNode = this->GetNamedDerivedNode(QmitkUSNavigationMarkerPlacement::DATANAME_TARGETSURFACE, QmitkUSNavigationMarkerPlacement::DATANAME_TUMOUR); m_TargetNode->SetBoolProperty("visible", true); // set lookup table of tumour node m_TargetNode->SetProperty("LookupTable", m_TargetColorLookupTableProperty); m_TargetUpdateFilter->SetTargetStructure(m_TargetNode); for (QVector>::iterator it = m_PlannedTargetNodes.begin(); it != m_PlannedTargetNodes.end(); ++it) { (*it)->SetBoolProperty("visible", true); } this->UpdateTargetDescriptions(); // m_TargetUpdateFilter->UpdateTargetScores(); return true; } bool QmitkUSNavigationStepPlacementPlanning::OnDeactivateStep() { ui->freezeImageButton->Unfreeze(); return true; } void QmitkUSNavigationStepPlacementPlanning::OnUpdate() { this->UpdateTargetColors(); // get navigation data source and make sure that it is not null mitk::NavigationDataSource::Pointer navigationDataSource = this->GetCombinedModality()->GetNavigationDataSource(); if (navigationDataSource.IsNull()) { MITK_ERROR("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepPunctuationIntervention") << "Navigation Data Source of Combined Modality must not be null."; mitkThrow() << "Navigation Data Source of Combined Modality must not be null."; } navigationDataSource->Update(); this->UpdateBodyMarkerStatus(navigationDataSource->GetOutput(m_ReferenceSensorIndex)); ui->freezeImageButton->setEnabled(m_BodyMarkerValid); mitk::PointSet::Pointer needleProjectionPointSet = m_NeedleProjectionFilter->GetProjection(); if (needleProjectionPointSet->GetSize() == 2) { m_TargetIntersectionFilter->SetTargetSurface(dynamic_cast(m_TargetNode->GetData())); m_TargetIntersectionFilter->SetLine(needleProjectionPointSet); m_TargetIntersectionFilter->CalculateIntersection(); if (m_TargetIntersectionFilter->GetIsIntersecting()) { // only enable button if body marker is in the tracking volume, too ui->placeTargetButton->setEnabled(m_BodyMarkerValid); ui->placeTargetButton->setToolTip(""); if (m_PlannedTargetNodes.size() == m_NumberOfTargets - 1) { mitk::PointSet::Pointer targetPointSet = mitk::PointSet::New(); mitk::PointSet::PointIdentifier n = 0; for (QVector>::iterator it = m_PlannedTargetNodes.begin(); it != m_PlannedTargetNodes.end(); ++it) { targetPointSet->InsertPoint(n++, (*it)->GetData()->GetGeometry()->GetOrigin()); } targetPointSet->InsertPoint(n, m_TargetIntersectionFilter->GetIntersectionPoint()); this->CalculatePlanningQuality(dynamic_cast(m_TargetNode->GetData()), targetPointSet); } } else { ui->placeTargetButton->setEnabled(false); ui->placeTargetButton->setToolTip( "Target cannot be placed as the needle path is not intersecting the target surface."); // no not show planning quality if not all nodes are planned for now // and there is no needle path intersection if (m_PlannedTargetNodes.size() < m_NumberOfTargets) { ui->angleDifferenceValue->setText(""); ui->centersOfMassValue->setText(""); } } } } void QmitkUSNavigationStepPlacementPlanning::OnSettingsChanged(const itk::SmartPointer settingsNode) { int numberOfTargets; if (settingsNode->GetIntProperty("settings.number-of-targets", numberOfTargets)) { m_NumberOfTargets = numberOfTargets; m_TargetUpdateFilter->SetNumberOfTargets(numberOfTargets); m_PlacementQualityCalculator->SetOptimalAngle(m_TargetUpdateFilter->GetOptimalAngle()); } std::string referenceSensorName; if (settingsNode->GetStringProperty("settings.reference-name-selected", referenceSensorName)) { m_ReferenceSensorName = referenceSensorName; } std::string needleSensorName; if (settingsNode->GetStringProperty("settings.needle-name-selected", needleSensorName)) { m_NeedleSensorName = needleSensorName; } this->UpdateSensorsNames(); } QString QmitkUSNavigationStepPlacementPlanning::GetTitle() { return "Placement Planning"; } QmitkUSAbstractNavigationStep::FilterVector QmitkUSNavigationStepPlacementPlanning::GetFilter() { FilterVector filterVector; filterVector.push_back(m_NodeDisplacementFilter.GetPointer()); filterVector.push_back(m_NeedleProjectionFilter.GetPointer()); return filterVector; } void QmitkUSNavigationStepPlacementPlanning::OnSetCombinedModality() { - mitk::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(false); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(false); if (combinedModality.IsNotNull()) { mitk::AffineTransform3D::Pointer calibration = combinedModality->GetCalibration(); if (calibration.IsNotNull()) { m_NeedleProjectionFilter->SetTargetPlane(calibration); } } ui->freezeImageButton->SetCombinedModality(combinedModality, m_ReferenceSensorIndex); this->UpdateSensorsNames(); } void QmitkUSNavigationStepPlacementPlanning::OnFreeze(bool freeze) { if (freeze) this->GetCombinedModality()->SetIsFreezed(true); if (freeze) { // load state machine and event config for data interactor m_PointMarkInteractor->LoadStateMachine("USPointMarkInteractions.xml", us::ModuleRegistry::GetModule("MitkUS")); m_PointMarkInteractor->SetEventConfig("globalConfig.xml"); this->CreateTargetNodesIfNecessary(); m_PointMarkInteractor->SetDataNode(m_PlannedTargetNodes.at(m_CurrentTargetIndex)); } else { m_PointMarkInteractor->SetDataNode(0); } if (!freeze) this->GetCombinedModality()->SetIsFreezed(false); } void QmitkUSNavigationStepPlacementPlanning::OnPlaceTargetButtonClicked() { this->CreateTargetNodesIfNecessary(); mitk::DataNode::Pointer currentNode = m_PlannedTargetNodes.at(m_CurrentTargetIndex); currentNode->SetData(this->CreateSphere(5)); currentNode->SetBoolProperty("surface_empty", false); mitk::PointSet::Pointer needleProjection = m_NeedleProjectionFilter->GetProjection(); m_TargetIntersectionFilter->SetTargetSurface(dynamic_cast(m_TargetNode->GetData())); m_TargetIntersectionFilter->SetLine(m_NeedleProjectionFilter->GetProjection()); m_TargetIntersectionFilter->CalculateIntersection(); mitk::Point3D intersectionPoint = m_TargetIntersectionFilter->GetIntersectionPoint(); currentNode->GetData()->GetGeometry()->SetOrigin(intersectionPoint); m_TargetUpdateFilter->SetControlNode(m_CurrentTargetIndex, currentNode); mitk::PointSet::Pointer plannedPath = mitk::PointSet::New(); m_PlannedNeedlePaths.at(m_CurrentTargetIndex)->SetData(plannedPath); plannedPath->SetPoint(0, needleProjection->GetPoint(0)); plannedPath->SetPoint(1, intersectionPoint); if (m_CurrentTargetIndex < m_NumberOfTargets - 1) { this->OnGoToNextTarget(); } else { this->UpdateTargetDescriptions(); } this->ReinitNodeDisplacementFilter(); MITK_INFO("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepPlacementPlanning") << "Target " << m_CurrentTargetIndex + 1 << " planned at position " << intersectionPoint << "."; } void QmitkUSNavigationStepPlacementPlanning::OnGoToPreviousTarget() { if (m_CurrentTargetIndex < 1) { mitkThrow() << "Cannot go to previous target as current target is first target."; } m_CurrentTargetIndex--; this->UpdateTargetDescriptions(); } void QmitkUSNavigationStepPlacementPlanning::OnGoToNextTarget() { m_CurrentTargetIndex++; this->UpdateTargetDescriptions(); } void QmitkUSNavigationStepPlacementPlanning::OnRemoveCurrentTargetClicked() { if (m_CurrentTargetIndex >= m_PlannedTargetNodes.size()) { MITK_WARN << "Cannot remove current target as there aren't as much planned target nodes."; return; } this->GetDataStorage()->Remove(m_PlannedTargetNodes.at(m_CurrentTargetIndex)); m_PlannedTargetNodes.remove(m_CurrentTargetIndex); this->GetDataStorage()->Remove(m_PlannedNeedlePaths.at(m_CurrentTargetIndex)); m_PlannedNeedlePaths.remove(m_CurrentTargetIndex); this->ReinitNodeDisplacementFilter(); for (int n = 0; n < m_PlannedTargetNodes.size(); ++n) { // set name of the target node according to its new index m_PlannedTargetNodes.at(n)->SetName( QString("Target %1").arg(n + 1, m_NumberOfTargets / 10 + 1, 10, QLatin1Char('0')).toStdString()); m_PlannedNeedlePaths.at(n)->SetName( QString("Target Path %1").arg(n + 1, m_NumberOfTargets / 10 + 1, 10, QLatin1Char('0')).toStdString()); } m_TargetUpdateFilter->RemovePositionOfTarget(m_CurrentTargetIndex); m_CurrentTargetIndex = m_PlannedTargetNodes.size(); this->UpdateTargetDescriptions(); MITK_INFO("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepPlacementPlanning") << "Planned target " << m_CurrentTargetIndex + 1 << " removed."; } void QmitkUSNavigationStepPlacementPlanning::CreateTargetNodesIfNecessary() { mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(); while (m_PlannedTargetNodes.size() <= m_CurrentTargetIndex) { QString targetNumber = QString("%1").arg(m_PlannedTargetNodes.size() + 1, m_NumberOfTargets / 10 + 1, 10, QLatin1Char('0')); mitk::DataNode::Pointer targetNode = this->GetNamedDerivedNodeAndCreate( (QString("Target ") + targetNumber).toStdString().c_str(), QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS); targetNode->SetOpacity(0.5); targetNode->SetBoolProperty("surface_empty", true); targetNode->SetData(mitk::Surface::New()); m_PlannedTargetNodes.push_back(targetNode); mitk::DataNode::Pointer targetPathNode = this->GetNamedDerivedNodeAndCreate((QString("Target Path ") + targetNumber).toStdString().c_str(), QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS_PATHS); targetPathNode->SetOpacity(0.5); targetPathNode->SetColor(1, 1, 1); targetPathNode->SetColor(1, 1, 1, nullptr, "contourcolor"); targetPathNode->SetBoolProperty("show contour", true); m_PlannedNeedlePaths.push_back(targetPathNode); mitk::Surface::Pointer pathSurface = mitk::Surface::New(); targetPathNode->SetData(pathSurface); } } void QmitkUSNavigationStepPlacementPlanning::UpdateTargetCoordinates(mitk::DataNode *dataNode) { bool surfaceEmpty; if (dataNode->GetBoolProperty("surface_empty", surfaceEmpty) && surfaceEmpty) { mitk::Point3D origin = dataNode->GetData()->GetGeometry()->GetOrigin(); dataNode->SetData(this->CreateSphere(5)); dataNode->SetBoolProperty("surface_empty", false); dataNode->GetData()->GetGeometry()->SetOrigin(origin); } this->ReinitNodeDisplacementFilter(); mitk::BaseData *baseData = dataNode->GetData(); if (!baseData) { mitkThrow() << "Data of the data node must not be null."; } mitk::BaseGeometry::Pointer geometry = baseData->GetGeometry(); if (geometry.IsNull()) { mitkThrow() << "Geometry of the data node must not be null."; } m_TargetUpdateFilter->SetControlNode(m_CurrentTargetIndex, dataNode); MITK_INFO("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepPlacementPlanning") << "Target " << m_CurrentTargetIndex + 1 << " planned at position " << geometry->GetOrigin() << "."; if (ui->freezeImageButton->isChecked()) { ui->freezeImageButton->Unfreeze(); if (m_CurrentTargetIndex < m_NumberOfTargets - 1) { this->OnGoToNextTarget(); } } this->UpdateTargetDescriptions(); } void QmitkUSNavigationStepPlacementPlanning::UpdateTargetColors() { if (m_TargetNode.IsNull()) { return; } m_TargetNode->SetColor(1, 1, 1); mitk::BaseData *targetNodeData = m_TargetNode->GetData(); if (targetNodeData == 0) { return; } mitk::Surface::Pointer targetNodeSurface = dynamic_cast(targetNodeData); vtkSmartPointer targetNodeSurfaceVtk = targetNodeSurface->GetVtkPolyData(); vtkFloatArray *targetScoreScalars = dynamic_cast( targetNodeSurface->GetVtkPolyData()->GetPointData()->GetScalars("USNavigation::PlanningPlacement")); if (!targetScoreScalars) { return; } unsigned int numberOfTupels = targetScoreScalars->GetNumberOfTuples(); vtkSmartPointer colors = vtkSmartPointer::New(); colors->SetNumberOfComponents(1); colors->SetNumberOfTuples(numberOfTupels); colors->SetName("Colors"); double markerScore; for (unsigned int n = 0; n < numberOfTupels; n++) { targetScoreScalars->GetTuple(n, &markerScore); colors->SetTuple(n, &markerScore); } if (numberOfTupels > 0) { targetNodeSurfaceVtk->GetPointData()->SetScalars(colors); targetNodeSurfaceVtk->GetPointData()->Update(); } } void QmitkUSNavigationStepPlacementPlanning::UpdateTargetDescriptions() { ui->previousButton->setEnabled(m_CurrentTargetIndex > 0); ui->nextButton->setEnabled(m_CurrentTargetIndex + 1 < m_PlannedTargetNodes.size()); ui->removeButton->setEnabled(m_PlannedTargetNodes.size() > 0); ui->currentTargetLabel->setText( QString("Planning Target %1 of %2").arg(m_CurrentTargetIndex + 1).arg(m_NumberOfTargets)); ui->removeButton->setEnabled(m_CurrentTargetIndex < m_PlannedTargetNodes.size()); this->CalculatePlanningQuality(); } void QmitkUSNavigationStepPlacementPlanning::GenerateTargetColorLookupTable() { vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetHueRange(0.0, 0.27); lookupTable->SetSaturationRange(1.0, 1.0); lookupTable->SetValueRange(1.0, 1.0); lookupTable->SetTableRange(0.0, 1.0); lookupTable->Build(); mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); lut->SetVtkLookupTable(lookupTable); m_TargetColorLookupTableProperty = mitk::LookupTableProperty::New(lut); } void QmitkUSNavigationStepPlacementPlanning::ReinitNodeDisplacementFilter() { m_NodeDisplacementFilter->ResetNodes(); for (QVector>::iterator it = m_PlannedTargetNodes.begin(); it != m_PlannedTargetNodes.end(); ++it) { if (it->IsNotNull() && (*it)->GetData() != 0) { m_NodeDisplacementFilter->AddNode(*it); } } for (QVector>::iterator it = m_PlannedNeedlePaths.begin(); it != m_PlannedNeedlePaths.end(); ++it) { if (it->IsNotNull() && (*it)->GetData() != 0) { m_NodeDisplacementFilter->AddNode(*it); } } } void QmitkUSNavigationStepPlacementPlanning::CalculatePlanningQuality() { if (m_PlannedTargetNodes.size() != m_NumberOfTargets) { ui->angleDifferenceLabel->setEnabled(false); ui->centersOfMassLabel->setEnabled(false); ui->allTargetsPlannedLabel->setEnabled(false); ui->angleDifferenceValue->setText(""); ui->centersOfMassValue->setText(""); return; } ui->angleDifferenceLabel->setEnabled(true); ui->centersOfMassLabel->setEnabled(true); ui->allTargetsPlannedLabel->setEnabled(true); mitk::PointSet::Pointer targetPointSet = mitk::PointSet::New(); mitk::PointSet::PointIdentifier n = 0; for (QVector>::iterator it = m_PlannedTargetNodes.begin(); it != m_PlannedTargetNodes.end(); ++it) { targetPointSet->InsertPoint(n++, (*it)->GetData()->GetGeometry()->GetOrigin()); } mitk::DataNode::Pointer planningQualityResult = this->CalculatePlanningQuality(dynamic_cast(m_TargetNode->GetData()), targetPointSet); emit SignalIntermediateResult(planningQualityResult); } mitk::DataNode::Pointer QmitkUSNavigationStepPlacementPlanning::CalculatePlanningQuality( mitk::Surface::Pointer targetSurface, mitk::PointSet::Pointer targetPoints) { if (targetSurface.IsNull()) { mitkThrow() << "Target surface must not be null."; } m_PlacementQualityCalculator->SetTargetSurface(targetSurface); m_PlacementQualityCalculator->SetTargetPoints(targetPoints); m_PlacementQualityCalculator->Update(); mitk::DataNode::Pointer planningQualityResult = mitk::DataNode::New(); planningQualityResult->SetName("PlanningQuality"); double centersOfMassDistance = m_PlacementQualityCalculator->GetCentersOfMassDistance(); ui->centersOfMassValue->setText(QString::number(centersOfMassDistance, 103, 2) + " mm"); planningQualityResult->SetFloatProperty("USNavigation::CentersOfMassDistance", centersOfMassDistance); if (m_PlannedTargetNodes.size() > 1) { double meanAnglesDifference = m_PlacementQualityCalculator->GetMeanAngleDifference(); ui->angleDifferenceValue->setText(QString::number(meanAnglesDifference, 103, 2) + QString::fromLatin1(" °")); planningQualityResult->SetFloatProperty("USNavigation::MeanAngleDifference", meanAnglesDifference); planningQualityResult->SetProperty( "USNavigation::AngleDifferences", mitk::GenericProperty::New(m_PlacementQualityCalculator->GetAngleDifferences())); } else { ui->angleDifferenceValue->setText("not valid for one point"); } return planningQualityResult; } itk::SmartPointer QmitkUSNavigationStepPlacementPlanning::CreateSphere(float) { mitk::Surface::Pointer surface = mitk::Surface::New(); // create a vtk sphere with fixed radius vtkSmartPointer vtkSphere = vtkSmartPointer::New(); vtkSphere->SetRadius(5); vtkSphere->SetCenter(0, 0, 0); vtkSphere->Update(); surface->SetVtkPolyData(vtkSphere->GetOutput()); return surface; } void QmitkUSNavigationStepPlacementPlanning::UpdateBodyMarkerStatus(mitk::NavigationData::Pointer bodyMarker) { if (bodyMarker.IsNull()) { MITK_ERROR("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepPunctuationIntervention") << "Current Navigation Data for body marker of Combined Modality must not be null."; mitkThrow() << "Current Navigation Data for body marker of Combined Modality must not be null."; } m_BodyMarkerValid = bodyMarker->IsDataValid(); // update body marker status label if (m_BodyMarkerValid) { ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #8bff8b; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); ui->bodyMarkerTrackingStatusLabel->setText("Body marker is inside the tracking volume."); } else { ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #ff7878; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); ui->bodyMarkerTrackingStatusLabel->setText("Body marker is not inside the tracking volume."); } } void QmitkUSNavigationStepPlacementPlanning::UpdateSensorsNames() { - mitk::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(false); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(false); if (combinedModality.IsNull()) { return; } mitk::NavigationDataSource::Pointer navigationDataSource = combinedModality->GetNavigationDataSource(); if (navigationDataSource.IsNull()) { return; } if (!m_NeedleSensorName.empty()) { try { m_NeedleSensorIndex = navigationDataSource->GetOutputIndex(m_NeedleSensorName); } catch (const std::exception &e) { MITK_WARN("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepPlacementPlanning") << "Cannot get index for needle sensor name: " << e.what(); } } if (this->GetNavigationStepState() >= QmitkUSAbstractNavigationStep::State_Active) { m_NeedleProjectionFilter->SelectInput(m_NeedleSensorIndex); } if (!m_ReferenceSensorName.empty()) { try { m_ReferenceSensorIndex = navigationDataSource->GetOutputIndex(m_ReferenceSensorName); } catch (const std::exception &e) { MITK_WARN("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepPlacementPlanning") << "Cannot get index for reference sensor name: " << e.what(); } } if (this->GetNavigationStepState() >= QmitkUSAbstractNavigationStep::State_Active) { m_NodeDisplacementFilter->SelectInput(m_ReferenceSensorIndex); } ui->freezeImageButton->SetCombinedModality(combinedModality, m_ReferenceSensorIndex); } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.ui similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.ui diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.cpp similarity index 93% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.cpp index 1fdbbb5ded..86635094b7 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.cpp @@ -1,283 +1,294 @@ /*=================================================================== 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 "QmitkUSNavigationStepPunctuationIntervention.h" #include "ui_QmitkUSNavigationStepPunctuationIntervention.h" #include "mitkNeedleProjectionFilter.h" #include "../Widgets/QmitkZoneProgressBar.h" #include "../QmitkUSNavigationMarkerPlacement.h" #include "usModuleRegistry.h" #include QmitkUSNavigationStepPunctuationIntervention::QmitkUSNavigationStepPunctuationIntervention(QWidget *parent) : QmitkUSAbstractNavigationStep(parent), m_Ui(new Ui::QmitkUSNavigationStepPunctuationIntervention), m_ZoneNodes(nullptr), m_NeedleProjectionFilter(mitk::NeedleProjectionFilter::New()), m_NeedleNavigationTool(mitk::NavigationTool::New()), m_OldColors(), m_SphereSource(vtkSmartPointer::New()), m_OBBTree(vtkSmartPointer::New()), m_IntersectPoints(vtkSmartPointer::New()) { m_Ui->setupUi(this); connect(m_Ui->m_AddNewAblationZone, SIGNAL(clicked()), this, SLOT(OnAddAblationZoneClicked())); connect(m_Ui->m_ShowToolAxisN, SIGNAL(stateChanged(int)), this, SLOT(OnShowToolAxisEnabled(int))); connect(m_Ui->m_EnableAblationMarking, SIGNAL(clicked()), this, SLOT(OnEnableAblationZoneMarkingClicked())); connect(m_Ui->m_AblationZoneSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnAblationZoneSizeSliderChanged(int))); m_Ui->m_AblationZonesBox->setVisible(false); } void QmitkUSNavigationStepPunctuationIntervention::SetNeedleMetaData(mitk::NavigationTool::Pointer needleNavigationTool) { this->m_NeedleNavigationTool = needleNavigationTool; } void QmitkUSNavigationStepPunctuationIntervention::OnEnableAblationZoneMarkingClicked() { if(m_Ui->m_EnableAblationMarking->isChecked()) m_Ui->m_AblationZonesBox->setVisible(true); else m_Ui->m_AblationZonesBox->setVisible(false); } void QmitkUSNavigationStepPunctuationIntervention::OnAblationZoneSizeSliderChanged(int size) { int id = m_Ui->m_AblationZonesList->currentRow(); if (id!=-1) {emit AblationZoneChanged(id,size);} }// void QmitkUSNavigationStepPunctuationIntervention::OnAddAblationZoneClicked() { QListWidgetItem* newItem = new QListWidgetItem("Ablation Zone (initial size: " + QString::number(m_Ui->m_AblationZoneSizeSlider->value()) + " mm)", m_Ui->m_AblationZonesList); newItem->setSelected(true); emit AddAblationZoneClicked(m_Ui->m_AblationZoneSizeSlider->value()); } QmitkUSNavigationStepPunctuationIntervention::~QmitkUSNavigationStepPunctuationIntervention() { mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(false); if ( dataStorage.IsNotNull() ) { // remove needle path from data storage if it is there mitk::DataNode::Pointer node = this->GetNamedDerivedNode ("Needle Path", QmitkUSAbstractNavigationStep::DATANAME_BASENODE); if ( node.IsNotNull() ) { dataStorage->Remove(node); } } delete m_Ui; } bool QmitkUSNavigationStepPunctuationIntervention::OnStartStep() { // create node for Needle Projection mitk::DataNode::Pointer node = this->GetNamedDerivedNodeAndCreate ("Needle Path", QmitkUSAbstractNavigationStep::DATANAME_BASENODE); node->SetData(m_NeedleProjectionFilter->GetProjection()); node->SetBoolProperty("show contour", true); - m_NeedleProjectionFilter->SetToolAxisForFilter(m_NeedleNavigationTool->GetToolAxis()); + //m_NeedleProjectionFilter->SetToolAxisForFilter(m_NeedleNavigationTool->GetToolAxis()); return true; } bool QmitkUSNavigationStepPunctuationIntervention::OnRestartStep() { return this->OnActivateStep(); } bool QmitkUSNavigationStepPunctuationIntervention::OnFinishStep() { mitk::DataNode::Pointer finishPunctionResult = mitk::DataNode::New(); finishPunctionResult->SetName("PunctionResult"); mitk::Point3D needlePos = m_NeedleProjectionFilter->GetOutput(0)->GetPosition(); mitk::Quaternion needleRot = m_NeedleProjectionFilter->GetOutput(0)->GetOrientation(); finishPunctionResult->SetProperty("USNavigation::TipPositionEnd", mitk::Point3dProperty::New(needlePos)); MITK_INFO("USNavigationLogging") << "Instrument tip at end: " <ClearZones(); mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(); // add progress bars for risk zone nodes m_ZoneNodes = dataStorage->GetDerivations(dataStorage->GetNamedNode(QmitkUSNavigationMarkerPlacement::DATANAME_ZONES)); // add zones to the widgets for risk structures for (mitk::DataStorage::SetOfObjects::ConstIterator it = m_ZoneNodes->Begin(); it != m_ZoneNodes->End(); ++it) { m_Ui->riskStructuresRangeWidget->AddZone(it->Value()); float rgb[3]; it->Value()->GetColor(rgb); mitk::Color color; color.SetRed(rgb[0]); color.SetGreen(rgb[1]); color.SetBlue(rgb[2]); m_OldColors[it->Value()] = color; } m_NeedleProjectionFilter->SelectInput(0); return true; } void QmitkUSNavigationStepPunctuationIntervention::OnShowToolAxisEnabled(int enabled) { if (enabled == 0) { m_NeedleProjectionFilter->ShowToolAxis(false); } else { m_NeedleProjectionFilter->ShowToolAxis(true); } } void QmitkUSNavigationStepPunctuationIntervention::OnUpdate() { + if (this->GetCombinedModality(false).IsNull()) return; // get navigation data source and make sure that it is not null mitk::NavigationDataSource::Pointer navigationDataSource = - this->GetCombinedModality()->GetNavigationDataSource(); + this->GetCombinedModality()->GetNavigationDataSource(); + if ( navigationDataSource.IsNull() ) { + MITK_ERROR("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepPunctuationIntervention") << "Navigation Data Source of Combined Modality must not be null."; mitkThrow() << "Navigation Data Source of Combined Modality must not be null."; } // update body marker this->UpdateBodyMarkerStatus(navigationDataSource->GetOutput(1)); // update critical structures this->UpdateCriticalStructures(navigationDataSource->GetOutput(0),m_NeedleProjectionFilter->GetProjection()); + m_NeedleProjectionFilter->Update(); + //Update Distance to US image mitk::Point3D point1 = m_NeedleProjectionFilter->GetProjection()->GetPoint(0); mitk::Point3D point2 = m_NeedleProjectionFilter->GetProjection()->GetPoint(1); double distance = point1.EuclideanDistanceTo(point2); m_Ui->m_DistanceToUSPlane->setText(QString::number(distance) + " mm"); } void QmitkUSNavigationStepPunctuationIntervention::OnSettingsChanged(const itk::SmartPointer settingsNode) { if ( settingsNode.IsNull() ) { return; } } QString QmitkUSNavigationStepPunctuationIntervention::GetTitle() { return "Computer-assisted Intervention"; } bool QmitkUSNavigationStepPunctuationIntervention::GetIsRestartable() { return false; } QmitkUSNavigationStepPunctuationIntervention::FilterVector QmitkUSNavigationStepPunctuationIntervention::GetFilter() { return FilterVector(1, m_NeedleProjectionFilter.GetPointer()); } void QmitkUSNavigationStepPunctuationIntervention::OnSetCombinedModality() { - mitk::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(false); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(false); if ( combinedModality.IsNotNull() ) { + m_NeedleProjectionFilter->ConnectTo(combinedModality->GetNavigationDataSource()); + // set calibration of the combined modality to the needle projection filter - mitk::AffineTransform3D::Pointer calibration = combinedModality->GetCalibration(); - if ( calibration.IsNotNull() ) + mitk::AffineTransform3D::Pointer usPlaneTransform = combinedModality->GetUSPlaneTransform(); + if (usPlaneTransform.IsNotNull()) { - m_NeedleProjectionFilter->SetTargetPlane(calibration); + m_NeedleProjectionFilter->SetTargetPlane(usPlaneTransform); } } + else + { + MITK_WARN << "CombinedModality is null!"; + } } void QmitkUSNavigationStepPunctuationIntervention::ClearZones() { m_Ui->riskStructuresRangeWidget->ClearZones(); } void QmitkUSNavigationStepPunctuationIntervention::UpdateBodyMarkerStatus(mitk::NavigationData::Pointer bodyMarker) { if ( bodyMarker.IsNull() ) { MITK_ERROR("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepPunctuationIntervention") << "Current Navigation Data for body marker of Combined Modality must not be null."; mitkThrow() << "Current Navigation Data for body marker of Combined Modality must not be null."; } bool valid = bodyMarker->IsDataValid(); // update body marker status label if (valid) { m_Ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #8bff8b; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); m_Ui->bodyMarkerTrackingStatusLabel->setText("Body marker is inside the tracking volume."); } else { m_Ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #ff7878; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); m_Ui->bodyMarkerTrackingStatusLabel->setText("Body marker is not inside the tracking volume."); } m_Ui->riskStructuresRangeGroupBox->setEnabled(valid); } void QmitkUSNavigationStepPunctuationIntervention::UpdateCriticalStructures(mitk::NavigationData::Pointer needle, mitk::PointSet::Pointer path) { // update the distances for the risk structures widget m_Ui->riskStructuresRangeWidget->UpdateDistancesToNeedlePosition(needle); //iterate through all zones for (mitk::DataStorage::SetOfObjects::ConstIterator it = m_ZoneNodes->Begin(); it != m_ZoneNodes->End(); ++it) { mitk::DataNode::Pointer currentNode = it->Value(); //get center point and radius float radius = -1; mitk::Point3D center; currentNode->GetFloatProperty("zone.size", radius); center = currentNode->GetData()->GetGeometry()->GetIndexToWorldTransform()->GetTranslation(); mitk::Point3D point0 = path->GetPoint(0); mitk::Point3D point1 = path->GetPoint(1); if (CheckSphereLineIntersection(center,radius,point0,point1)) {currentNode->SetColor(mitk::IGTColor_WARNING);} else {currentNode->SetColor(m_OldColors[currentNode]);} } } bool QmitkUSNavigationStepPunctuationIntervention::CheckSphereLineIntersection(mitk::Point3D& sphereOrigin, float& sphereRadius, mitk::Point3D& lineStart, mitk::Point3D& lineEnd) { double center[3] = {sphereOrigin[0],sphereOrigin[1],sphereOrigin[2]}; m_SphereSource->SetCenter(center); m_SphereSource->SetRadius(sphereRadius); m_SphereSource->Update(); m_OBBTree->SetDataSet(m_SphereSource->GetOutput()); m_OBBTree->BuildLocator(); double lineP0[3] = {lineStart[0], lineStart[1], lineStart[2]}; double lineP1[3] = {lineEnd[0], lineEnd[1], lineEnd[2]}; m_OBBTree->IntersectWithLine(lineP0, lineP1, m_IntersectPoints, nullptr); if (m_IntersectPoints->GetNumberOfPoints() > 0) {return true;} else {return false;} } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.ui similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.ui diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.cpp similarity index 97% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.cpp index db3c0c8b0c..781dc5ad12 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.cpp @@ -1,427 +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 "QmitkUSNavigationStepTumourSelection.h" #include "ui_QmitkUSNavigationStepTumourSelection.h" #include "usModuleRegistry.h" #include "mitkDataNode.h" #include "mitkSurface.h" #include "mitkUSCombinedModality.h" #include "../Interactors/mitkUSZonesInteractor.h" #include "mitkNodeDisplacementFilter.h" #include "QmitkUSNavigationStepCombinedModality.h" #include "../QmitkUSNavigationMarkerPlacement.h" #include "mitkIOUtil.h" #include "vtkSmartPointer.h" #include "vtkDoubleArray.h" #include "vtkPolyData.h" #include "vtkPointData.h" #include "vtkWarpScalar.h" QmitkUSNavigationStepTumourSelection::QmitkUSNavigationStepTumourSelection(QWidget* parent) : QmitkUSAbstractNavigationStep(parent), m_targetSelectionOptional(false), m_SecurityDistance(0), m_Interactor(mitk::USZonesInteractor::New()), m_NodeDisplacementFilter(mitk::NodeDisplacementFilter::New()), m_StateMachineFilename("USZoneInteractions.xml"), m_ReferenceSensorIndex(1), m_ListenerChangeNode(this, &QmitkUSNavigationStepTumourSelection::TumourNodeChanged), ui(new Ui::QmitkUSNavigationStepTumourSelection) { ui->setupUi(this); connect(ui->freezeImageButton, SIGNAL(SignalFreezed(bool)), this, SLOT(OnFreeze(bool))); connect(ui->tumourSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnTumourSizeChanged(int))); connect(ui->deleteTumourButton, SIGNAL(clicked()), this, SLOT(OnDeleteButtonClicked())); m_SphereColor = mitk::Color(); //default color: green m_SphereColor[0] = 0; m_SphereColor[1] = 255; m_SphereColor[2] = 0; } void QmitkUSNavigationStepTumourSelection::SetTumorColor(mitk::Color c) { m_SphereColor = c; } void QmitkUSNavigationStepTumourSelection::SetTargetSelectionOptional(bool t) { m_targetSelectionOptional = t; } QmitkUSNavigationStepTumourSelection::~QmitkUSNavigationStepTumourSelection() { delete ui; } bool QmitkUSNavigationStepTumourSelection::OnStartStep() { m_TumourNode = this->GetNamedDerivedNodeAndCreate( QmitkUSNavigationMarkerPlacement::DATANAME_TUMOUR, QmitkUSAbstractNavigationStep::DATANAME_BASENODE); m_TumourNode->SetColor(m_SphereColor[0], m_SphereColor[1], m_SphereColor[2]); // load state machine and event config for data interactor m_Interactor->LoadStateMachine(m_StateMachineFilename, us::ModuleRegistry::GetModule("MitkUS")); m_Interactor->SetEventConfig("globalConfig.xml"); this->GetDataStorage()->ChangedNodeEvent.AddListener(m_ListenerChangeNode); m_TargetSurfaceNode = this->GetNamedDerivedNodeAndCreate( QmitkUSNavigationMarkerPlacement::DATANAME_TARGETSURFACE, QmitkUSNavigationMarkerPlacement::DATANAME_TUMOUR); // do not show the surface until this is requested m_TargetSurfaceNode->SetBoolProperty("visible", false); // make sure that scalars will be renderer on the surface m_TargetSurfaceNode->SetBoolProperty("scalar visibility", true); m_TargetSurfaceNode->SetBoolProperty("color mode", true); m_TargetSurfaceNode->SetBoolProperty("Backface Culling", true); return true; } bool QmitkUSNavigationStepTumourSelection::OnStopStep() { // make sure that imaging isn't freezed anymore ui->freezeImageButton->Unfreeze(); m_NodeDisplacementFilter->ResetNodes(); mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(false); if (dataStorage.IsNotNull()) { // remove target surface node from data storage, if available there if (m_TargetSurfaceNode.IsNotNull()) { dataStorage->Remove(m_TargetSurfaceNode); } dataStorage->ChangedNodeEvent.RemoveListener(m_ListenerChangeNode); dataStorage->Remove(m_TumourNode); m_TumourNode = 0; } MITK_INFO("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepTumourSelection") << "Removing tumour."; return true; } bool QmitkUSNavigationStepTumourSelection::OnRestartStep() { ui->tumourSizeExplanationLabel->setEnabled(false); ui->tumourSizeLabel->setEnabled(false); ui->tumourSizeSlider->setEnabled(false); ui->deleteTumourButton->setEnabled(false); ui->tumourSizeSlider->blockSignals(true); ui->tumourSizeSlider->setValue(0); ui->tumourSizeSlider->blockSignals(false); return QmitkUSAbstractNavigationStep::OnRestartStep(); } bool QmitkUSNavigationStepTumourSelection::OnFinishStep() { // make sure that the surface has the right extent (in case the // tumor size was changed since the initial surface creation) m_TargetSurfaceNode->SetData(this->CreateTargetSurface()); return true; } bool QmitkUSNavigationStepTumourSelection::OnActivateStep() { m_Interactor = mitk::USZonesInteractor::New(); m_Interactor->LoadStateMachine(m_StateMachineFilename, us::ModuleRegistry::GetModule("MitkUS")); m_Interactor->SetEventConfig("globalConfig.xml"); - m_NodeDisplacementFilter->SelectInput(m_ReferenceSensorIndex); + m_NodeDisplacementFilter->ConnectTo(this->GetCombinedModality()->GetNavigationDataSource()); + m_NodeDisplacementFilter->SelectInput(1);//m_ReferenceSensorIndex //target selection is optional if (m_targetSelectionOptional) { emit SignalReadyForNextStep(); } return true; } bool QmitkUSNavigationStepTumourSelection::OnDeactivateStep() { m_Interactor->SetDataNode(0); bool value; if (m_TumourNode.IsNotNull() && !(m_TumourNode->GetBoolProperty("zone.created", value) && value)) { m_TumourNode->SetData(0); } // make sure that imaging isn't freezed anymore ui->freezeImageButton->Unfreeze(); return true; } void QmitkUSNavigationStepTumourSelection::OnUpdate() { if (m_NavigationDataSource.IsNull()) { return; } m_NavigationDataSource->Update(); + m_NodeDisplacementFilter->Update(); bool valid = m_NavigationDataSource->GetOutput(m_ReferenceSensorIndex)->IsDataValid(); if (valid) { ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #8bff8b; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); ui->bodyMarkerTrackingStatusLabel->setText("Body marker is inside the tracking volume."); } else { ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #ff7878; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); ui->bodyMarkerTrackingStatusLabel->setText("Body marker is not inside the tracking volume."); } ui->freezeImageButton->setEnabled(valid); bool created; if (m_TumourNode.IsNull() || !m_TumourNode->GetBoolProperty("zone.created", created) || !created) { ui->tumourSearchExplanationLabel->setEnabled(valid); } } void QmitkUSNavigationStepTumourSelection::OnSettingsChanged(const itk::SmartPointer settingsNode) { if (settingsNode.IsNull()) { return; } float securityDistance; if (settingsNode->GetFloatProperty("settings.security-distance", securityDistance)) { m_SecurityDistance = securityDistance; } std::string stateMachineFilename; if (settingsNode->GetStringProperty("settings.interaction-concept", stateMachineFilename) && stateMachineFilename != m_StateMachineFilename) { m_StateMachineFilename = stateMachineFilename; m_Interactor->LoadStateMachine(stateMachineFilename, us::ModuleRegistry::GetModule("MitkUS")); } std::string referenceSensorName; if (settingsNode->GetStringProperty("settings.reference-name-selected", referenceSensorName)) { m_ReferenceSensorName = referenceSensorName; } this->UpdateReferenceSensorName(); } QString QmitkUSNavigationStepTumourSelection::GetTitle() { return "Localisation of Tumour Position"; } QmitkUSAbstractNavigationStep::FilterVector QmitkUSNavigationStepTumourSelection::GetFilter() { return FilterVector(1, m_NodeDisplacementFilter.GetPointer()); } void QmitkUSNavigationStepTumourSelection::OnFreeze(bool freezed) { if (freezed) this->GetCombinedModality()->SetIsFreezed(true); ui->tumourSelectionExplanation1Label->setEnabled(freezed); ui->tumourSelectionExplanation2Label->setEnabled(freezed); if (freezed) { if (!m_TumourNode->GetData()) { // load state machine and event config for data interactor m_Interactor->LoadStateMachine(m_StateMachineFilename, us::ModuleRegistry::GetModule("MitkUS")); m_Interactor->SetEventConfig("globalConfig.xml"); m_Interactor->SetDataNode(m_TumourNode); // feed reference pose to node displacement filter m_NodeDisplacementFilter->SetInitialReferencePose(this->GetCombinedModality()->GetNavigationDataSource()->GetOutput(m_ReferenceSensorIndex)->Clone()); } } else { bool value; if (m_TumourNode->GetBoolProperty("zone.created", value) && value) { ui->freezeImageButton->setEnabled(false); ui->tumourSearchExplanationLabel->setEnabled(false); } } if (!freezed) this->GetCombinedModality()->SetIsFreezed(false); } void QmitkUSNavigationStepTumourSelection::OnSetCombinedModality() { - mitk::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(false); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(false); if (combinedModality.IsNotNull()) { m_NavigationDataSource = combinedModality->GetNavigationDataSource(); } else { m_NavigationDataSource = 0; } ui->freezeImageButton->SetCombinedModality(combinedModality, m_ReferenceSensorIndex); this->UpdateReferenceSensorName(); } void QmitkUSNavigationStepTumourSelection::OnTumourSizeChanged(int size) { m_TumourNode->SetFloatProperty("zone.size", static_cast(size)); mitk::USZonesInteractor::UpdateSurface(m_TumourNode); MITK_INFO("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepTumourSelection") << "Changing tumour radius to " << size << "."; } void QmitkUSNavigationStepTumourSelection::OnDeleteButtonClicked() { this->OnRestartStep(); } void QmitkUSNavigationStepTumourSelection::TumourNodeChanged(const mitk::DataNode* dataNode) { // only changes of tumour node are of interest if (dataNode != m_TumourNode) { return; } float size; dataNode->GetFloatProperty("zone.size", size); ui->tumourSizeSlider->setValue(static_cast(size)); bool created; if (dataNode->GetBoolProperty("zone.created", created) && created) { if (ui->freezeImageButton->isChecked()) { m_NodeDisplacementFilter->AddNode(const_cast(dataNode)); m_TargetSurfaceNode->SetData(this->CreateTargetSurface()); m_NodeDisplacementFilter->AddNode(m_TargetSurfaceNode); MITK_INFO("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepTumourSelection") << "Tumour created with center " << dataNode->GetData()->GetGeometry()->GetOrigin() << " and radius " << size << "."; mitk::DataNode::Pointer tumourResultNode = mitk::DataNode::New(); tumourResultNode->SetName("TumourResult"); tumourResultNode->SetProperty("USNavigation::TumourCenter", mitk::Point3dProperty::New(dataNode->GetData()->GetGeometry()->GetOrigin())); tumourResultNode->SetProperty("USNavigation::TumourRadius", mitk::DoubleProperty::New(size)); emit SignalIntermediateResult(tumourResultNode); ui->freezeImageButton->Unfreeze(); } ui->tumourSearchExplanationLabel->setEnabled(false); ui->tumourSizeExplanationLabel->setEnabled(true); ui->tumourSizeLabel->setEnabled(true); ui->tumourSizeSlider->setEnabled(true); ui->deleteTumourButton->setEnabled(true); emit SignalReadyForNextStep(); } } mitk::Surface::Pointer QmitkUSNavigationStepTumourSelection::CreateTargetSurface() { mitk::Surface::Pointer tumourSurface = dynamic_cast(m_TumourNode->GetData()); if (tumourSurface.IsNull()) { MITK_WARN << "No target selected, cannot create surface!"; return mitk::Surface::New(); //return a empty surface in this case... } // make a deep copy of the tumour surface polydata vtkSmartPointer tumourSurfaceVtk = vtkSmartPointer::New(); tumourSurfaceVtk->DeepCopy(tumourSurface->GetVtkPolyData()); // create scalars for moving every point the same size onto its normal vector vtkSmartPointer scalars = vtkSmartPointer::New(); int numberOfPoints = tumourSurfaceVtk->GetNumberOfPoints(); scalars->SetNumberOfTuples(numberOfPoints); // set scalars for warp filter for (vtkIdType i = 0; i < numberOfPoints; ++i) { scalars->SetTuple1(i, m_SecurityDistance * 10); } tumourSurfaceVtk->GetPointData()->SetScalars(scalars); vtkSmartPointer warpScalar = vtkSmartPointer::New(); warpScalar->SetInputData(tumourSurfaceVtk); warpScalar->SetScaleFactor(1); // use the scalars themselves warpScalar->Update(); vtkSmartPointer targetSurfaceVtk = warpScalar->GetPolyDataOutput(); // set the moved points to the deep copied tumour surface; this is // necessary as setting the targetSurfaceVtk as polydata for the // targetSurface would result in flat shading for the surface (seems // to be a bug in MITK or VTK) tumourSurfaceVtk->SetPoints(targetSurfaceVtk->GetPoints()); mitk::Surface::Pointer targetSurface = mitk::Surface::New(); targetSurface->SetVtkPolyData(tumourSurfaceVtk); targetSurface->GetGeometry()->SetOrigin(tumourSurface->GetGeometry()->GetOrigin()); return targetSurface; } itk::SmartPointer QmitkUSNavigationStepTumourSelection::GetTumourNodeDisplacementFilter() { return m_NodeDisplacementFilter; } void QmitkUSNavigationStepTumourSelection::UpdateReferenceSensorName() { if (m_NavigationDataSource.IsNull()) { return; } if (!m_ReferenceSensorName.empty()) { try { m_ReferenceSensorIndex = m_NavigationDataSource->GetOutputIndex(m_ReferenceSensorName); } catch (const std::exception &e) { MITK_WARN("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepTumourSelection") << "Cannot get index for reference sensor name: " << e.what(); } } if (this->GetNavigationStepState() >= QmitkUSAbstractNavigationStep::State_Active) { + MITK_INFO << "############### " << m_NodeDisplacementFilter->GetNumberOfIndexedInputs(); m_NodeDisplacementFilter->SelectInput(m_ReferenceSensorIndex); } ui->freezeImageButton->SetCombinedModality(this->GetCombinedModality(false), m_ReferenceSensorIndex); } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.ui similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.ui diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.cpp similarity index 95% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.cpp index ffe7a26b38..652b537af5 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.cpp @@ -1,269 +1,272 @@ /*=================================================================== 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 "QmitkUSNavigationStepZoneMarking.h" #include "ui_QmitkUSNavigationStepZoneMarking.h" #include "mitkNodeDisplacementFilter.h" #include "../QmitkUSNavigationMarkerPlacement.h" QmitkUSNavigationStepZoneMarking::QmitkUSNavigationStepZoneMarking(QWidget *parent) : QmitkUSAbstractNavigationStep(parent), m_ZoneDisplacementFilter(mitk::NodeDisplacementFilter::New()), m_ReferenceSensorIndex(1), m_CurrentlyAddingZone(false), ui(new Ui::QmitkUSNavigationStepZoneMarking) { ui->setupUi(this); connect( ui->freezeButton, SIGNAL(SignalFreezed(bool)), this, SLOT(OnFreeze(bool)) ); connect( ui->zonesWidget, SIGNAL(ZoneAdded()), this, SLOT(OnZoneAdded()) ); connect( ui->zonesWidget, SIGNAL(ZoneRemoved()), this, SLOT(OnZoneRemoved()) ); connect(ui->showStructureList, SIGNAL(stateChanged(int)), this, SLOT(OnShowListClicked(int))); ui->zonesLabel->setVisible(false); ui->zonesWidget->setVisible(false); } void QmitkUSNavigationStepZoneMarking::OnShowListClicked(int state) { ui->zonesLabel->setVisible(state); ui->zonesWidget->setVisible(state); } QmitkUSNavigationStepZoneMarking::~QmitkUSNavigationStepZoneMarking() { delete ui; } bool QmitkUSNavigationStepZoneMarking::OnStartStep() { this->GetNamedDerivedNodeAndCreate(QmitkUSNavigationMarkerPlacement::DATANAME_ZONES, QmitkUSAbstractNavigationStep::DATANAME_BASENODE); ui->zonesWidget->SetDataStorage(this->GetDataStorage(), QmitkUSNavigationMarkerPlacement::DATANAME_ZONES); return true; } bool QmitkUSNavigationStepZoneMarking::OnStopStep() { m_ZoneDisplacementFilter->ResetNodes(); ui->zonesWidget->OnResetZones(); m_ZoneNodes.clear(); // remove zone nodes from the data storage mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(false); if ( dataStorage.IsNotNull() ) { mitk::DataNode::Pointer baseNode = dataStorage->GetNamedNode(QmitkUSAbstractNavigationStep::DATANAME_BASENODE); if ( baseNode.IsNotNull() ) { dataStorage->Remove(dataStorage->GetNamedDerivedNode(QmitkUSNavigationMarkerPlacement::DATANAME_ZONES, baseNode)); } } return true; } bool QmitkUSNavigationStepZoneMarking::OnFinishStep() { return true; } bool QmitkUSNavigationStepZoneMarking::OnActivateStep() { + m_ZoneDisplacementFilter->ConnectTo(this->GetCombinedModality()->GetNavigationDataSource()); m_ZoneDisplacementFilter->SelectInput(m_ReferenceSensorIndex); emit SignalReadyForNextStep(); return true; } bool QmitkUSNavigationStepZoneMarking::OnDeactivateStep() { ui->freezeButton->Unfreeze(); return true; } void QmitkUSNavigationStepZoneMarking::OnUpdate() { if (m_NavigationDataSource.IsNull()) { return; } m_NavigationDataSource->Update(); + m_ZoneDisplacementFilter->Update(); bool valid = m_NavigationDataSource->GetOutput(m_ReferenceSensorIndex)->IsDataValid(); if (valid) { ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #8bff8b; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); ui->bodyMarkerTrackingStatusLabel->setText("Body marker is inside the tracking volume."); } else { ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #ff7878; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); ui->bodyMarkerTrackingStatusLabel->setText("Body marker is not inside the tracking volume."); } ui->freezeButton->setEnabled(valid); } void QmitkUSNavigationStepZoneMarking::OnSettingsChanged(const itk::SmartPointer settingsNode) { if ( settingsNode.IsNull() ) { return; } std::string stateMachineFilename; if ( settingsNode->GetStringProperty("settings.interaction-concept", stateMachineFilename) && stateMachineFilename != m_StateMachineFilename ) { m_StateMachineFilename = stateMachineFilename; ui->zonesWidget->SetStateMachineFilename(stateMachineFilename); } std::string referenceSensorName; if ( settingsNode->GetStringProperty("settings.reference-name-selected", referenceSensorName) ) { m_ReferenceSensorName = referenceSensorName; } this->UpdateReferenceSensorName(); } QString QmitkUSNavigationStepZoneMarking::GetTitle() { return "Critical Structures"; } QmitkUSAbstractNavigationStep::FilterVector QmitkUSNavigationStepZoneMarking::GetFilter() { return FilterVector(1, m_ZoneDisplacementFilter.GetPointer()); } void QmitkUSNavigationStepZoneMarking::OnFreeze(bool freezed) { if (freezed) this->GetCombinedModality()->SetIsFreezed(true); ui->zoneAddingExplanationLabel->setEnabled(freezed); if ( freezed ) { m_CurrentlyAddingZone = true; ui->zonesWidget->OnStartAddingZone(); // feed reference pose to node displacement filter m_ZoneDisplacementFilter->SetInitialReferencePose(this->GetCombinedModality()->GetNavigationDataSource()->GetOutput(m_ReferenceSensorIndex)->Clone()); } else if ( m_CurrentlyAddingZone ) { m_CurrentlyAddingZone = false; ui->zonesWidget->OnAbortAddingZone(); } if (!freezed) this->GetCombinedModality()->SetIsFreezed(false); } void QmitkUSNavigationStepZoneMarking::OnZoneAdded() { m_CurrentlyAddingZone = false; ui->freezeButton->Unfreeze(); ui->zoneAddingExplanationLabel->setEnabled(ui->freezeButton->isChecked()); mitk::DataStorage::SetOfObjects::ConstPointer zoneNodesSet = ui->zonesWidget->GetZoneNodes(); for (mitk::DataStorage::SetOfObjects::ConstIterator it = zoneNodesSet->Begin(); it != zoneNodesSet->End(); ++it) { // add all zones to zone filter which aren't added until now if ( std::find(m_ZoneNodes.begin(), m_ZoneNodes.end(), it->Value()) == m_ZoneNodes.end() ) { // logging center point and radius float radius = -1; it->Value()->GetFloatProperty("zone.size", radius); MITK_INFO("QmitkUSNavigationStepZoneMarking")("QmitkUSAbstractNavigationStep") << "Risk zone (" << it->Value()->GetName() << ") added with center " << it->Value()->GetData()->GetGeometry()->GetOrigin() << " and radius " << radius << "."; m_ZoneNodes.push_back(it->Value()); m_ZoneDisplacementFilter->AddNode(it->Value()); } } } void QmitkUSNavigationStepZoneMarking::OnZoneRemoved() { mitk::DataStorage::SetOfObjects::ConstPointer zoneNodesSet = ui->zonesWidget->GetZoneNodes(); for ( int n = m_ZoneNodes.size() - 1; n >= 0; --n ) { bool found = false; // test if the node can be found in the set of zone nodes for (mitk::DataStorage::SetOfObjects::ConstIterator itSet = zoneNodesSet->Begin(); itSet != zoneNodesSet->End(); ++itSet) { if ( m_ZoneNodes.at(n) == itSet->Value() ) { found = true; break; } } if ( ! found ) { MITK_INFO("QmitkUSNavigationStepZoneMarking")("QmitkUSAbstractNavigationStep") << "Risk zone (" << m_ZoneNodes.at(n)->GetName() << ") removed."; m_ZoneNodes.erase(m_ZoneNodes.begin()+n); m_ZoneDisplacementFilter->RemoveNode(n); } } } void QmitkUSNavigationStepZoneMarking::OnSetCombinedModality() { - mitk::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(false); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(false); if (combinedModality.IsNotNull()) { m_NavigationDataSource = combinedModality->GetNavigationDataSource(); } ui->freezeButton->SetCombinedModality(combinedModality, m_ReferenceSensorIndex); this->UpdateReferenceSensorName(); } void QmitkUSNavigationStepZoneMarking::UpdateReferenceSensorName() { if ( m_NavigationDataSource.IsNull() ) { return; } if ( ! m_ReferenceSensorName.empty() ) { try { - m_ReferenceSensorIndex = m_NavigationDataSource->GetOutputIndex(m_ReferenceSensorName); + //m_ReferenceSensorIndex = m_NavigationDataSource->GetOutputIndex(m_ReferenceSensorName); + m_ReferenceSensorIndex = 1; } catch ( const std::exception &e ) { MITK_WARN("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepZoneMarking") << "Cannot get index for reference sensor name: " << e.what(); } } if ( this->GetNavigationStepState() >= QmitkUSAbstractNavigationStep::State_Active ) { m_ZoneDisplacementFilter->SelectInput(m_ReferenceSensorIndex); } ui->freezeButton->SetCombinedModality(this->GetCombinedModality(false), m_ReferenceSensorIndex); } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.ui similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.ui diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationRemoveDelegate.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationRemoveDelegate.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationRemoveDelegate.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationRemoveDelegate.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationRemoveDelegate.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationRemoveDelegate.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationRemoveDelegate.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationRemoveDelegate.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationUpdateDepthDelegate.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationUpdateDepthDelegate.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationUpdateDepthDelegate.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationUpdateDepthDelegate.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationUpdateDepthDelegate.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationUpdateDepthDelegate.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationUpdateDepthDelegate.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationUpdateDepthDelegate.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationsDataModel.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationsDataModel.cpp similarity index 94% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationsDataModel.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationsDataModel.cpp index 0258f3b058..988a5a9170 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationsDataModel.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationsDataModel.cpp @@ -1,250 +1,250 @@ /*=================================================================== 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 "QmitkUSNavigationCalibrationsDataModel.h" #include #include #include #include #include #include QmitkUSNavigationCalibrationsDataModel::QmitkUSNavigationCalibrationsDataModel(QObject *parent) : QAbstractTableModel(parent), m_ListenerDeviceChanged(this, &QmitkUSNavigationCalibrationsDataModel::OnDeviceChanged) { } QmitkUSNavigationCalibrationsDataModel::~QmitkUSNavigationCalibrationsDataModel() { if ( m_CombinedModality.IsNotNull() ) { m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); } } - void QmitkUSNavigationCalibrationsDataModel::SetCombinedModality(mitk::USCombinedModality::Pointer combinedModality) + void QmitkUSNavigationCalibrationsDataModel::SetCombinedModality(mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality) { if ( m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull() ) { m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); } m_CombinedModality = combinedModality; if ( m_CombinedModality.IsNotNull() ) { m_ControlInterfaceBMode = m_CombinedModality->GetControlInterfaceBMode(); // make sure that the combined modality is active as this may be // necessary to get the available depths - if ( m_CombinedModality->GetDeviceState() < mitk::USDevice::State_Connected ) { m_CombinedModality->Connect(); } - if ( m_CombinedModality->GetDeviceState() == mitk::USDevice::State_Connected ) { m_CombinedModality->Activate(); } + if ( m_CombinedModality->GetUltrasoundDevice()->GetDeviceState() < mitk::USDevice::State_Connected ) { m_CombinedModality->GetUltrasoundDevice()->Connect(); } + if ( m_CombinedModality->GetUltrasoundDevice()->GetDeviceState() == mitk::USDevice::State_Connected ) { m_CombinedModality->GetUltrasoundDevice()->Activate(); } if ( m_CombinedModality->GetUltrasoundDevice().IsNotNull() ) { m_CombinedModality->GetUltrasoundDevice()->AddPropertyChangedListener(m_ListenerDeviceChanged); } } // as the combined modality was changed, an old table model // would not be valid anymore this->beginResetModel(); this->endResetModel(); } void QmitkUSNavigationCalibrationsDataModel::OnDeviceChanged(const std::string&, const std::string&) { this->beginResetModel(); this->endResetModel(); } /** \brief Return number of rows of the model. */ int QmitkUSNavigationCalibrationsDataModel::rowCount ( const QModelIndex & ) const { if ( m_ControlInterfaceBMode.IsNull() ) { return 1; // only one default depth can be assumed } else { return m_ControlInterfaceBMode->GetScanningDepthValues().size(); } } /** \brief Return number of columns (3) of the model. */ int QmitkUSNavigationCalibrationsDataModel::columnCount ( const QModelIndex & ) const { return 3; } /** \brief Return names for the columns, numbers for the rows and invalid for DisplayRole. */ QVariant QmitkUSNavigationCalibrationsDataModel::headerData ( int section, Qt::Orientation orientation, int role ) const { if ( role != Qt::DisplayRole ) { return QVariant(QVariant::Invalid); } if ( orientation == Qt::Horizontal ) { switch ( section ) { case 0: return QVariant("Depth"); case 1: return QVariant("Calibrated"); case 2: return QVariant(""); } } return QVariant(QVariant::Invalid); } /** \brief Return selectable and enabled for column 1 (size); selectable, enabled and editable for every other column. */ Qt::ItemFlags QmitkUSNavigationCalibrationsDataModel::flags ( const QModelIndex & ) const { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; } /** \brief Return model data of the selected cell. */ QVariant QmitkUSNavigationCalibrationsDataModel::data ( const QModelIndex & index, int role ) const { if ( m_CombinedModality.IsNull() ) { return QVariant(QVariant::Invalid); } std::vector scanningDepthValues = m_ControlInterfaceBMode.IsNull() ? std::vector(1,0) : m_ControlInterfaceBMode->GetScanningDepthValues(); // make sure that row and column index fit data borders if (index.row() >= this->rowCount() || index.column() >= this->columnCount()) { return QVariant(QVariant::Invalid); } double currentDepth = 0; if ( m_ControlInterfaceBMode.IsNotNull() ) { currentDepth = m_ControlInterfaceBMode->GetScanningDepth(); } bool isCalibratedForCurrentDepth = m_CombinedModality->GetCalibration(QString::number(scanningDepthValues.at(index.row())).toStdString()).IsNotNull(); switch (role) { case Qt::BackgroundColorRole: { if ( isCalibratedForCurrentDepth ) { return QVariant(QBrush(QColor(125, 255, 125))); } else { return QVariant(QBrush(QColor(255, 125, 125))); } break; } case Qt::FontRole: { if ( scanningDepthValues.at(index.row()) == currentDepth ) { QFont qFont; qFont.setBold(true); return qFont; } else { return QVariant::Invalid; } } case Qt::DecorationRole: { if ( index.column() == 2 ) { if ( isCalibratedForCurrentDepth ) { return QIcon(":/USNavigation/process-stop.png"); } } else { return QVariant::Invalid; } } case Qt::EditRole: case Qt::DisplayRole: { switch ( index.column() ) { case 0: { return QVariant::fromValue(scanningDepthValues.at(index.row())); } case 1: { if ( m_ControlInterfaceBMode.IsNull() ) { // use the current zoom level (which is assumed to be the only one), // when no b mode controls are available return QVariant(m_CombinedModality->GetCalibration().IsNotNull()); } else { return QVariant(isCalibratedForCurrentDepth); } } case 2: { return QVariant(""); } } break; } case Qt::ToolTipRole: { if ( index.column() == 2 && isCalibratedForCurrentDepth ) { return QVariant(QString("Remove calibration for depth ") + QString::number(scanningDepthValues.at(index.row())) + " on mouse click."); } break; } } return QVariant(QVariant::Invalid); } /** \brief Set model data for the selected cell. */ bool QmitkUSNavigationCalibrationsDataModel::setData ( const QModelIndex & index, const QVariant & value, int ) { if ( m_CombinedModality.IsNull() || index.column() != 2 || value != false ) return false; if ( m_ControlInterfaceBMode.IsNull() ) { m_CombinedModality->RemoveCalibration(); } else { m_CombinedModality->RemoveCalibration(QString::number(m_ControlInterfaceBMode->GetScanningDepthValues().at(index.row())).toStdString()); } emit dataChanged(this->index(index.row(), 0), this->index(index.row(), 1)); return true; } /** \brief Remove given rows from the model. * \param removeFromDataStorage zone nodes are removed from the data storage too, if this is set to true */ bool QmitkUSNavigationCalibrationsDataModel::removeRows ( int, int, const QModelIndex&, bool ) { return false; } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationsDataModel.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationsDataModel.h similarity index 91% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationsDataModel.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationsDataModel.h index 358b15fb10..db16f09fcd 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationCalibrationsDataModel.h +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationCalibrationsDataModel.h @@ -1,74 +1,74 @@ /*=================================================================== 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 QMITKUSNAVIGATIONCALIBRATIONSDATAMODEL_H #define QMITKUSNAVIGATIONCALIBRATIONSDATAMODEL_H #include #include #include namespace mitk { - class USCombinedModality; + class AbstractUltrasoundTrackerDevice; class USControlInterfaceBMode; class USControlInterfaceProbes; } class QmitkUSNavigationCalibrationsDataModel : public QAbstractTableModel { Q_OBJECT public: explicit QmitkUSNavigationCalibrationsDataModel(QObject *parent = 0); virtual ~QmitkUSNavigationCalibrationsDataModel(); - void SetCombinedModality(itk::SmartPointer combinedModality); + void SetCombinedModality(itk::SmartPointer combinedModality); void OnDeviceChanged(const std::string&, const std::string&); /** \brief Return number of rows of the model. */ virtual int rowCount ( const QModelIndex & parent = QModelIndex() ) const; /** \brief Return number of columns (3) of the model. */ virtual int columnCount ( const QModelIndex & parent = QModelIndex() ) const; /** \brief Return names for the columns, numbers for the rows and invalid for DisplayRole. */ virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; /** \brief Return selectable and enabled for column 1 (size); selectable, enabled and editable for every other column. */ virtual Qt::ItemFlags flags ( const QModelIndex & index ) const; /** \brief Return model data of the selected cell. */ virtual QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const; /** \brief Set model data for the selected cell. */ virtual bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); using QAbstractTableModel::removeRows; /** \brief Remove given rows from the model. * \param removeFromDataStorage zone nodes are removed from the data storage too, if this is set to true */ virtual bool removeRows ( int row, int count, const QModelIndex& parent, bool removeFromDataStorage ); private: - itk::SmartPointer m_CombinedModality; + itk::SmartPointer m_CombinedModality; itk::SmartPointer m_ControlInterfaceBMode; mitk::MessageDelegate2 m_ListenerDeviceChanged; }; #endif // QMITKUSNAVIGATIONCALIBRATIONSDATAMODEL_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationMarkerPlacement.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.cpp similarity index 54% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationMarkerPlacement.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.cpp index 3cc40c3395..65a4152199 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationMarkerPlacement.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.cpp @@ -1,874 +1,830 @@ /*=================================================================== 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 "QmitkUSNavigationMarkerPlacement.h" #include "ui_QmitkUSNavigationMarkerPlacement.h" #include "NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h" #include "NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h" #include "NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.h" #include "NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h" #include "NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.h" #include "NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.h" #include "SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.h" +#include "mitkAbstractUltrasoundTrackerDevice.h" #include "mitkIRenderingManager.h" #include "mitkNodeDisplacementFilter.h" -#include "mitkUSCombinedModality.h" +#include "mitkTrackedUltrasound.h" #include -#include "IO/mitkUSNavigationExperimentLogging.h" #include "IO/mitkUSNavigationStepTimer.h" #include #include #include #include #include #include #include "QmitkRenderWindow.h" #include "QmitkStdMultiWidget.h" #include "QmitkStdMultiWidgetEditor.h" -#include "mitkLayoutAnnotationRenderer.h" #include "mitkCameraController.h" +#include "mitkLayoutAnnotationRenderer.h" #include // scene serialization #include #include #include #include #include const std::string QmitkUSNavigationMarkerPlacement::VIEW_ID = "org.mitk.views.usmarkerplacement"; const char *QmitkUSNavigationMarkerPlacement::DATANAME_TUMOUR = "Tumour"; const char *QmitkUSNavigationMarkerPlacement::DATANAME_TARGETSURFACE = "Target Surface"; const char *QmitkUSNavigationMarkerPlacement::DATANAME_ZONES = "Zones"; const char *QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS = "Targets"; const char *QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS_PATHS = "Target Paths"; const char *QmitkUSNavigationMarkerPlacement::DATANAME_REACHED_TARGETS = "Reached Targets"; QmitkUSNavigationMarkerPlacement::QmitkUSNavigationMarkerPlacement() : m_Parent(nullptr), - m_NavigationSteps(), - m_UpdateTimer(new QTimer(this)), - m_ImageAndNavigationDataLoggingTimer(new QTimer(this)), - m_StdMultiWidget(nullptr), - m_CombinedModality(nullptr), - m_ReinitAlreadyDone(false), - m_IsExperimentRunning(false), - m_CurrentApplicationName(), - m_NavigationStepTimer(mitk::USNavigationStepTimer::New()), - m_ExperimentLogging(mitk::USNavigationExperimentLogging::New()), - m_IconRunning(QPixmap(":/USNavigation/record.png")), - m_IconNotRunning(QPixmap(":/USNavigation/record-gray.png")), - m_ResultsDirectory(), - m_ExperimentName(), - m_ExperimentResultsSubDirectory(), - m_NavigationStepNames(), - m_LoggingBackend(), - m_USImageLoggingFilter(mitk::USImageLoggingFilter::New()), - m_NavigationDataRecorder(mitk::NavigationDataRecorder::New()), - m_TargetNodeDisplacementFilter(nullptr), - m_AblationZonesDisplacementFilter(mitk::NodeDisplacementFilter::New()), - m_AblationZonesVector(), - m_NeedleIndex(0), - m_MarkerIndex(1), - m_SceneNumber(1), - m_WarnOverlay(mitk::TextAnnotation2D::New()), - m_NavigationDataSource(nullptr), - m_CurrentStorage(nullptr), - m_ListenerDeviceChanged(this, &QmitkUSNavigationMarkerPlacement::OnCombinedModalityPropertyChanged), - ui(new Ui::QmitkUSNavigationMarkerPlacement ) + m_UpdateTimer(new QTimer(this)), + m_ImageAndNavigationDataLoggingTimer(new QTimer(this)), + m_StdMultiWidget(nullptr), + m_CombinedModality(nullptr), + m_ReinitAlreadyDone(false), + m_IsExperimentRunning(false), + m_CurrentApplicationName(), + m_NavigationStepTimer(mitk::USNavigationStepTimer::New()), + m_IconRunning(QPixmap(":/USNavigation/record.png")), + m_IconNotRunning(QPixmap(":/USNavigation/record-gray.png")), + m_ResultsDirectory(), + m_ExperimentName(), + m_ExperimentResultsSubDirectory(), + m_NavigationStepNames(), + m_LoggingBackend(), + m_USImageLoggingFilter(mitk::USImageLoggingFilter::New()), + m_NavigationDataRecorder(mitk::NavigationDataRecorder::New()), + m_TargetNodeDisplacementFilter(nullptr), + m_AblationZonesDisplacementFilter(mitk::NodeDisplacementFilter::New()), + m_ToolVisualizationFilter(nullptr), + m_AblationZonesVector(), + m_NeedleIndex(0), + m_MarkerIndex(1), + m_SceneNumber(1), + m_WarnOverlay(mitk::TextAnnotation2D::New()), + m_NavigationDataSource(nullptr), + m_CurrentStorage(nullptr), + m_ImageStreamNode(nullptr), + ui(new Ui::QmitkUSNavigationMarkerPlacement) { connect(m_UpdateTimer, SIGNAL(timeout()), this, SLOT(OnTimeout())); connect( m_ImageAndNavigationDataLoggingTimer, SIGNAL(timeout()), this, SLOT(OnImageAndNavigationDataLoggingTimeout())); // scale running (and not running) icon the specific height m_IconRunning = m_IconRunning.scaledToHeight(20, Qt::SmoothTransformation); m_IconNotRunning = m_IconNotRunning.scaledToHeight(20, Qt::SmoothTransformation); - // set prefix for experiment logging (only keys with this prefix are taken - // into consideration - m_ExperimentLogging->SetKeyPrefix("USNavigation::"); - m_UpdateTimer->start(33); // every 33 Milliseconds = 30 Frames/Second } QmitkUSNavigationMarkerPlacement::~QmitkUSNavigationMarkerPlacement() { - // remove listener for ultrasound device changes - if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) - { - m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); - } - - // remove listener for ultrasound device changes - if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) - { - m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); - } - + this->GetDataStorage()->Remove(m_InstrumentNode); delete ui; } void QmitkUSNavigationMarkerPlacement::OnChangeAblationZone(int id, int newSize) { if ((static_cast(m_AblationZonesVector.size()) < id) || (id < 0)) { return; } MITK_INFO << "Ablation Zone " << id << " changed, new size: " << newSize; // create a vtk sphere with given radius vtkSmartPointer vtkSphere = vtkSmartPointer::New(); vtkSphere->SetRadius(newSize / 2); vtkSphere->SetCenter(0, 0, 0); vtkSphere->SetPhiResolution(20); vtkSphere->SetThetaResolution(20); vtkSphere->Update(); mitk::Surface::Pointer zoneSurface = dynamic_cast(m_AblationZonesVector.at(id)->GetData()); zoneSurface->SetVtkPolyData(vtkSphere->GetOutput()); } void QmitkUSNavigationMarkerPlacement::OnAddAblationZone(int size) { m_AblationZonesDisplacementFilter->SetInitialReferencePose( m_CombinedModality->GetNavigationDataSource()->GetOutput(m_MarkerIndex)); mitk::DataNode::Pointer NewAblationZone = mitk::DataNode::New(); mitk::Point3D origin = m_CombinedModality->GetNavigationDataSource()->GetOutput(m_NeedleIndex)->GetPosition(); MITK_INFO("USNavigationLogging") << "Ablation Zone Added, initial size: " << size << ", origin: " << origin; mitk::Surface::Pointer zone = mitk::Surface::New(); // create a vtk sphere with given radius vtkSmartPointer vtkSphere = vtkSmartPointer::New(); vtkSphere->SetRadius(size / 2); vtkSphere->SetCenter(0, 0, 0); vtkSphere->SetPhiResolution(20); vtkSphere->SetThetaResolution(20); vtkSphere->Update(); zone->SetVtkPolyData(vtkSphere->GetOutput()); // set vtk sphere and origin to data node (origin must be set // again, because of the new sphere set as data) NewAblationZone->SetData(zone); NewAblationZone->GetData()->GetGeometry()->SetOrigin(origin); mitk::Color SphereColor = mitk::Color(); // default color SphereColor[0] = 102; SphereColor[1] = 0; SphereColor[2] = 204; NewAblationZone->SetColor(SphereColor); NewAblationZone->SetOpacity(0.3); // set name of zone std::stringstream name; name << "Ablation Zone" << m_AblationZonesVector.size(); NewAblationZone->SetName(name.str()); // add zone to filter m_AblationZonesDisplacementFilter->AddNode(NewAblationZone); m_AblationZonesVector.push_back(NewAblationZone); this->GetDataStorage()->Add(NewAblationZone); } void QmitkUSNavigationMarkerPlacement::CreateQtPartControl(QWidget *parent) { m_Parent = parent; ui->setupUi(parent); - connect(ui->navigationProcessWidget, - SIGNAL(SignalCombinedModalityChanged(itk::SmartPointer)), - this, - SLOT(OnCombinedModalityChanged(itk::SmartPointer))); - - connect(ui->navigationProcessWidget, - SIGNAL(SignalSettingsChanged(itk::SmartPointer)), - this, - SLOT(OnSettingsChanged(itk::SmartPointer))); - - connect(ui->navigationProcessWidget, - SIGNAL(SignalActiveNavigationStepChanged(int)), - this, - SLOT(OnActiveNavigationStepChanged(int))); - - connect(ui->navigationProcessWidget, - SIGNAL(SignalActiveNavigationStepChangeRequested(int)), - this, - SLOT(OnNextNavigationStepInitialization(int))); - connect(ui->startExperimentButton, SIGNAL(clicked()), this, SLOT(OnStartExperiment())); connect(ui->finishExperimentButton, SIGNAL(clicked()), this, SLOT(OnFinishExperiment())); connect(ui->m_enableNavigationLayout, SIGNAL(clicked()), this, SLOT(OnChangeLayoutClicked())); connect(ui->m_RenderWindowSelection, SIGNAL(valueChanged(int)), this, SLOT(OnRenderWindowSelection())); connect(ui->m_RefreshView, SIGNAL(clicked()), this, SLOT(OnRefreshView())); - connect(ui->navigationProcessWidget, - SIGNAL(SignalIntermediateResult(const itk::SmartPointer)), - this, - SLOT(OnIntermediateResultProduced(const itk::SmartPointer))); + m_BaseNode = this->GetDataStorage()->GetNamedNode(QmitkUSAbstractNavigationStep::DATANAME_BASENODE); + if (m_BaseNode.IsNull()) + { + m_BaseNode = mitk::DataNode::New(); + m_BaseNode->SetName(QmitkUSAbstractNavigationStep::DATANAME_BASENODE); + this->GetDataStorage()->Add(m_BaseNode); + } - ui->navigationProcessWidget->SetDataStorage(this->GetDataStorage()); + connect(ui->m_CtToUsRegistrationWidget, SIGNAL(GetCursorPosition()), this, SLOT(OnGetCursorPosition())); + connect(ui->m_CtToUsRegistrationWidget, SIGNAL(ActualizeCtToUsRegistrationWidget()), this, SLOT(OnActualizeCtToUsRegistrationWidget())); + connect(ui->m_initializeCtToUsRegistration, SIGNAL(clicked()), this, SLOT(OnInitializeCtToUsRegistration())); + connect(ui->m_initializeTargetMarking, SIGNAL(clicked()), this, SLOT(OnInitializeTargetMarking())); + connect(ui->m_initializeCritStructureMarking, SIGNAL(clicked()), this, SLOT(OnInitializeCriticalStructureMarking())); + connect(ui->m_initializeNavigation, SIGNAL(clicked()), this, SLOT(OnInitializeNavigation())); // indicate that no experiment is running at start ui->runningLabel->setPixmap(m_IconNotRunning); - ui->navigationProcessWidget->SetSettingsWidget(new QmitkUSNavigationCombinedSettingsWidget(m_Parent)); + connect(ui->m_settingsWidget, + SIGNAL(SettingsChanged(itk::SmartPointer)), + this, + SLOT(OnSettingsChanged(itk::SmartPointer))); +} + +void QmitkUSNavigationMarkerPlacement::ReInitializeSettingsNodesAndImageStream() +{ + //If update timer is not stopped (signals stopped), setting the m_CombinedModality + // will cause a crash of the workbench in some times. + m_UpdateTimer->blockSignals(true); + m_UpdateTimer->stop(); + m_SettingsNode = mitk::DataNode::New(); + ui->m_settingsWidget->OnSetSettingsNode(m_SettingsNode, true); + InitImageStream(); + m_CombinedModality = ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality(); + // Having set the m_CombinedModality reactivate the update timer again + m_UpdateTimer->start(50); // every 50 Milliseconds = 20 Frames/Second + m_UpdateTimer->blockSignals(false); +} + +void QmitkUSNavigationMarkerPlacement::OnGetCursorPosition() +{ + mitk::Point3D centroid = this->GetRenderWindowPart()->GetSelectedPosition(); + ui->m_CtToUsRegistrationWidget->OnCalculateTRE(centroid); +} + +void QmitkUSNavigationMarkerPlacement::OnActualizeCtToUsRegistrationWidget() +{ + m_SettingsNode = mitk::DataNode::New(); + ui->m_settingsWidget->OnSetSettingsNode(m_SettingsNode, true); + this->InitImageStream(); + + if (ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality().IsNull()) + { + return; + } + ui->m_CtToUsRegistrationWidget->SetCombinedModality( + ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality()); + + m_CombinedModality = ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality(); + + if (!m_StdMultiWidget) + { + // try to get the standard multi widget if it couldn't be got before + mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); + + QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindow); + + // if there is a standard multi widget now, disable the level window and + // change the layout to 2D up and 3d down + if (multiWidgetEditor) + { + m_StdMultiWidget = multiWidgetEditor->GetStdMultiWidget(); + SetTwoWindowView(); + } + } + else + { + this->OnRefreshView(); + } + m_UpdateTimer->start(50); // every 50 Milliseconds = 20 Frames/Second +} + +void QmitkUSNavigationMarkerPlacement::OnInitializeCtToUsRegistration() +{ + ui->m_CtToUsRegistrationWidget->SetDataStorage(this->GetDataStorage()); + ui->m_CtToUsRegistrationWidget->OnSettingsChanged(m_SettingsNode); + ui->m_CtToUsRegistrationWidget->OnActivateStep(); + ui->m_CtToUsRegistrationWidget->OnStartStep(); + ui->m_CtToUsRegistrationWidget->Update(); +} + + + +void QmitkUSNavigationMarkerPlacement::OnInitializeTargetMarking() +{ + ReInitializeSettingsNodesAndImageStream(); + ui->m_TargetMarkingWidget->SetCombinedModality(m_CombinedModality); + ui->m_TargetMarkingWidget->SetDataStorage(this->GetDataStorage()); + ui->m_TargetMarkingWidget->OnSettingsChanged(m_SettingsNode); + ui->m_TargetMarkingWidget->OnActivateStep(); + ui->m_TargetMarkingWidget->OnStartStep(); + ui->m_TargetMarkingWidget->Update(); +} +void QmitkUSNavigationMarkerPlacement::OnInitializeCriticalStructureMarking() +{ + ReInitializeSettingsNodesAndImageStream(); + ui->m_CriticalStructuresWidget->SetCombinedModality(m_CombinedModality); + ui->m_CriticalStructuresWidget->SetDataStorage(this->GetDataStorage()); + ui->m_CriticalStructuresWidget->OnSettingsChanged(m_SettingsNode); + ui->m_CriticalStructuresWidget->OnActivateStep(); + ui->m_CriticalStructuresWidget->OnStartStep(); + ui->m_CriticalStructuresWidget->Update(); +} +void QmitkUSNavigationMarkerPlacement::OnInitializeNavigation() +{ + ReInitializeSettingsNodesAndImageStream(); + ui->m_NavigationWidget->SetCombinedModality(m_CombinedModality); + ui->m_NavigationWidget->SetDataStorage(this->GetDataStorage()); + ui->m_NavigationWidget->OnSettingsChanged(m_SettingsNode); + ui->m_NavigationWidget->OnActivateStep(); + ui->m_NavigationWidget->OnStartStep(); + ui->m_NavigationWidget->Update(); + + // test if it is tracked US, if yes add visualization filter + if (m_CombinedModality->GetIsTrackedUltrasoundActive()) + { + m_InstrumentNode = mitk::DataNode::New(); + m_InstrumentNode->SetName("Tracked US Instrument"); + m_InstrumentNode->SetData( + m_CombinedModality->GetNavigationDataSource()->GetToolMetaData(0)->GetToolSurface()->Clone()); + this->GetDataStorage()->Add(m_InstrumentNode); + m_ToolVisualizationFilter = mitk::NavigationDataObjectVisualizationFilter::New(); + m_ToolVisualizationFilter->ConnectTo(m_CombinedModality->GetNavigationDataSource()); + m_ToolVisualizationFilter->SetRepresentationObject(0, m_InstrumentNode->GetData()); //caution: currently hard coded that instrument has id 0 + //set dummy objects to avoid spamming of console + mitk::Surface::Pointer dummyObject = mitk::Surface::New(); + m_ToolVisualizationFilter->SetRepresentationObject(1, dummyObject); + m_ToolVisualizationFilter->SetRepresentationObject(2, dummyObject); + + } +} + +void QmitkUSNavigationMarkerPlacement::InitImageStream() +{ + if (m_ImageStreamNode.IsNull()) + { + m_ImageStreamNode = mitk::DataNode::New(); + m_ImageStreamNode->SetName("US Navigation Viewing Stream"); + this->GetDataStorage()->Add(m_ImageStreamNode); + } } void QmitkUSNavigationMarkerPlacement::OnCombinedModalityPropertyChanged(const std::string &key, const std::string &) { if (key == mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH) { m_ReinitAlreadyDone = false; this->ReinitOnImage(); if (m_CombinedModality.IsNotNull() && !m_CombinedModality->GetIsCalibratedForCurrentStatus()) { mitk::LayoutAnnotationRenderer::AddAnnotation( m_WarnOverlay.GetPointer(), "stdmulti.widget1", mitk::LayoutAnnotationRenderer::TopLeft); MITK_WARN << "No calibration available for the selected ultrasound image depth."; } } } void QmitkUSNavigationMarkerPlacement::SetFocus() { this->ReinitOnImage(); } void QmitkUSNavigationMarkerPlacement::OnTimeout() { + if (m_CombinedModality.IsNull()) + return; + m_CombinedModality->Modified(); // shouldn't be nessecary ... fix in abstract ultrasound tracker device! + m_CombinedModality->Update(); + if (m_ToolVisualizationFilter.IsNotNull()) + { + m_ToolVisualizationFilter->Update(); + } + + ui->m_CtToUsRegistrationWidget->Update(); + ui->m_TargetMarkingWidget->Update(); + ui->m_CriticalStructuresWidget->Update(); + ui->m_NavigationWidget->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); + } + if (!m_StdMultiWidget) { // try to get the standard multi widget if it couldn't be got before mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindow); // if there is a standard multi widget now, disable the level window and // change the layout to 2D up and 3d down if (multiWidgetEditor) { m_StdMultiWidget = multiWidgetEditor->GetStdMultiWidget(); SetTwoWindowView(); } this->CreateOverlays(); } - if (m_CombinedModality.IsNotNull() && - !this->m_CombinedModality->GetIsFreezed()) // if the combined modality is freezed: do nothing + if (m_CombinedModality.IsNotNull() && !this->m_CombinedModality->GetIsFreezed()) // if the combined modality is freezed: do nothing { - ui->navigationProcessWidget->UpdateNavigationProgress(); m_AblationZonesDisplacementFilter->Update(); // update the 3D window only every fourth time to speed up the rendering (at least in 2D) this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); // make sure that a reinit was performed on the image this->ReinitOnImage(); } } void QmitkUSNavigationMarkerPlacement::OnEnableNavigationLayout() { MITK_INFO << "Navigation Layout"; // try to get the standard multi widget if it couldn't be got before mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindow); // if there is a standard multi widget now, disable the level window and // change the layout to 2D up and 3d down if (multiWidgetEditor) { m_StdMultiWidget = multiWidgetEditor->GetStdMultiWidget(); SetTwoWindowView(); } } void QmitkUSNavigationMarkerPlacement::OnRenderWindowSelection() { SetTwoWindowView(); } void QmitkUSNavigationMarkerPlacement::OnRefreshView() { if (!ui->m_enableNavigationLayout->isChecked()) OnResetStandardLayout(); else { - //Reinit the US Image Stream (this might be broken if there was a global reinit somewhere...) + // Reinit the US Image Stream (this might be broken if there was a global reinit somewhere...) try { - mitk::RenderingManager::GetInstance()->InitializeViews(//Reinit - this->GetDataStorage()//GetDataStorage - ->GetNamedNode("US Support Viewing Stream")->GetData()->GetTimeGeometry());//GetNode + mitk::RenderingManager::GetInstance()->InitializeViews( // Reinit + this + ->GetDataStorage() // GetDataStorage + ->GetNamedNode("US Viewing Stream - Image 0") + ->GetData() + ->GetTimeGeometry()); // GetNode } catch (...) { MITK_DEBUG << "No reinit possible"; } SetTwoWindowView(); } } void QmitkUSNavigationMarkerPlacement::SetTwoWindowView() { if (m_StdMultiWidget) { + MITK_INFO << "m_StdMultiWidget exists and not null"; m_StdMultiWidget->DisableStandardLevelWindow(); int i, j, k; switch (this->ui->m_RenderWindowSelection->value()) { - case 1: - mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetCameraController()->SetViewToCaudal(); - i = 2; j = 3; //other windows - k = 1; - break; - case 2: - mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetCameraController()->SetViewToSinister(); - i = 1; j = 3; - k = 2; - break; - case 3: - mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetCameraController()->SetViewToAnterior(); - i = 2; j = 1; - k = 3; - break; - default: - return; + case 1: + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4")) + ->GetCameraController() + ->SetViewToCaudal(); + i = 2; + j = 3; // other windows + k = 1; + break; + case 2: + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4")) + ->GetCameraController() + ->SetViewToSinister(); + i = 1; + j = 3; + k = 2; + break; + case 3: + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4")) + ->GetCameraController() + ->SetViewToAnterior(); + i = 2; + j = 1; + k = 3; + break; + default: + return; } m_StdMultiWidget->changeLayoutTo2DUpAnd3DDown(k); ////Crosshair invisible in 3D view - this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(i) + ".plane")-> - SetBoolProperty("visible", false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); - this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(j) + ".plane")-> - SetBoolProperty("visible", false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); - this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(k) + ".plane")-> - SetBoolProperty("visible", true, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); - this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(i) + ".plane")-> - SetIntProperty("Crosshair.Gap Size", 0); - this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(j) + ".plane")-> - SetIntProperty("Crosshair.Gap Size", 0); + this->GetDataStorage() + ->GetNamedNode("stdmulti.widget" + std::to_string(i) + ".plane") + ->SetBoolProperty("visible", + false, + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); + this->GetDataStorage() + ->GetNamedNode("stdmulti.widget" + std::to_string(j) + ".plane") + ->SetBoolProperty("visible", + false, + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); + this->GetDataStorage() + ->GetNamedNode("stdmulti.widget" + std::to_string(k) + ".plane") + ->SetBoolProperty("visible", + true, + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); + this->GetDataStorage() + ->GetNamedNode("stdmulti.widget" + std::to_string(i) + ".plane") + ->SetIntProperty("Crosshair.Gap Size", 0); + this->GetDataStorage() + ->GetNamedNode("stdmulti.widget" + std::to_string(j) + ".plane") + ->SetIntProperty("Crosshair.Gap Size", 0); } } void QmitkUSNavigationMarkerPlacement::OnResetStandardLayout() { - //reset render windows + // reset render windows mitk::DataNode::Pointer widget1 = this->GetDataStorage()->GetNamedNode("stdmulti.widget1.plane"); - if (widget1.IsNotNull()) { widget1->SetVisibility(true); } + if (widget1.IsNotNull()) + { + widget1->SetVisibility(true); + } mitk::DataNode::Pointer widget2 = this->GetDataStorage()->GetNamedNode("stdmulti.widget2.plane"); - if (widget2.IsNotNull()) { widget2->SetVisibility(true); } + if (widget2.IsNotNull()) + { + widget2->SetVisibility(true); + } mitk::DataNode::Pointer widget3 = this->GetDataStorage()->GetNamedNode("stdmulti.widget3.plane"); - if (widget3.IsNotNull()) { widget3->SetVisibility(true); } + if (widget3.IsNotNull()) + { + widget3->SetVisibility(true); + } m_StdMultiWidget->changeLayoutToDefault(); } void QmitkUSNavigationMarkerPlacement::OnChangeLayoutClicked() { - if (ui->m_enableNavigationLayout->isChecked()) OnEnableNavigationLayout(); - else OnResetStandardLayout(); + if (ui->m_enableNavigationLayout->isChecked()) + OnEnableNavigationLayout(); + else + OnResetStandardLayout(); } void QmitkUSNavigationMarkerPlacement::OnImageAndNavigationDataLoggingTimeout() { // update filter for logging navigation data and ultrasound images if (m_CombinedModality.IsNotNull()) { m_NavigationDataRecorder->Update(); // get last messages for logging filer and store them std::vector messages = m_LoggingBackend.GetNavigationMessages(); std::string composedMessage = ""; for (std::size_t i = 0; i < messages.size(); i++) { composedMessage += messages.at(i); } m_USImageLoggingFilter->AddMessageToCurrentImage(composedMessage); m_LoggingBackend.ClearNavigationMessages(); // update logging filter m_USImageLoggingFilter->Update(); } } void QmitkUSNavigationMarkerPlacement::OnStartExperiment() { // get name for the experiment by a QInputDialog bool ok; if (m_ExperimentName.isEmpty()) { // default: current date m_ExperimentName = QString::number(QDateTime::currentDateTime().date().year()) + "_" + - QString::number(QDateTime::currentDateTime().date().month()) + "_" + - QString::number(QDateTime::currentDateTime().date().day()) + "_experiment_" + - QString::number(QDateTime::currentDateTime().time().hour()) + "." + - QString::number(QDateTime::currentDateTime().time().minute()); + QString::number(QDateTime::currentDateTime().date().month()) + "_" + + QString::number(QDateTime::currentDateTime().date().day()) + "_experiment_" + + QString::number(QDateTime::currentDateTime().time().hour()) + "." + + QString::number(QDateTime::currentDateTime().time().minute()); } m_ExperimentName = QInputDialog::getText( m_Parent, QString("Experiment Name"), QString("Name of the Experiment"), QLineEdit::Normal, m_ExperimentName, &ok); MITK_INFO("USNavigationLogging") << "Experiment started: " << m_ExperimentName.toStdString(); if (ok && !m_ExperimentName.isEmpty()) { // display error message and call the function recursivly if a directory // with the given name already exists QDir experimentResultsDir(m_ResultsDirectory + QDir::separator() + m_ExperimentName); if (experimentResultsDir.exists()) { QMessageBox::critical( m_Parent, "Results Directory Exists", "The result directory already exists.\nPlease choose an other name."); this->OnStartExperiment(); } else { QDir(m_ResultsDirectory).mkdir(m_ExperimentName); m_ExperimentResultsSubDirectory = m_ResultsDirectory + QDir::separator() + m_ExperimentName; // experiment is running now ui->runningLabel->setPixmap(m_IconRunning); - ui->navigationProcessWidget->EnableInteraction(true); // (re)start timer for navigation step durations m_NavigationStepTimer->Reset(); m_NavigationStepTimer->SetOutputFileName( QString(m_ExperimentResultsSubDirectory + QDir::separator() + QString("durations.cvs")).toStdString()); - m_NavigationStepTimer->SetActiveIndex(0, m_NavigationSteps.at(0)->GetTitle().toStdString()); + m_NavigationStepTimer->SetActiveIndex(0, "Initialization"); ui->finishExperimentButton->setEnabled(true); ui->startExperimentButton->setDisabled(true); // initialize and register logging backend QString loggingFilename = m_ExperimentResultsSubDirectory + QDir::separator() + "logging.txt"; m_LoggingBackend.SetOutputFileName(loggingFilename.toStdString()); mbilog::RegisterBackend(&m_LoggingBackend); // initialize and start navigation data recorder form xml recording m_NavigationDataRecorder->StartRecording(); m_IsExperimentRunning = true; m_ImageAndNavigationDataLoggingTimer->start(1000); - - // (re)start experiment logging and set output file name - m_ExperimentLogging->Reset(); - m_ExperimentLogging->SetFileName( - QString(m_ExperimentResultsSubDirectory + QDir::separator() + "experiment-logging.xml").toStdString()); } } } void QmitkUSNavigationMarkerPlacement::OnFinishExperiment() { this->WaitCursorOn(); MITK_INFO("USNavigationLogging") << "Experiment finished!"; - MITK_INFO("USNavigationLogging") - << "Position/Orientation of needle tip: " - << (dynamic_cast(m_CombinedModality->GetTrackingDevice()->GetOutput(0)))->GetPosition(); + MITK_INFO("USNavigationLogging") << "Position/Orientation of needle tip: " + << (dynamic_cast( + m_CombinedModality->GetTrackingDeviceDataSource()->GetOutput(0))) + ->GetPosition(); MITK_INFO("USNavigationLogging") << "Position of target: " << m_TargetNodeDisplacementFilter->GetRawDisplacementNavigationData(0)->GetPosition(); MITK_INFO("USNavigationLogging") << "Total duration: " << m_NavigationStepTimer->GetTotalDuration(); - ui->navigationProcessWidget->FinishCurrentNavigationStep(); m_ImageAndNavigationDataLoggingTimer->stop(); ui->runningLabel->setPixmap(m_IconNotRunning); - ui->navigationProcessWidget->EnableInteraction(false); m_NavigationStepTimer->Stop(); - // make sure that the navigation process will be start from beginning at the - // next experiment - ui->navigationProcessWidget->ResetNavigationProcess(); - ui->finishExperimentButton->setDisabled(true); ui->startExperimentButton->setEnabled(true); MITK_INFO("USNavigationLogging") << "Writing logging data to " << m_ExperimentResultsSubDirectory.toStdString(); // save ultrasound images to the file system QDir(m_ExperimentResultsSubDirectory).mkdir("ImageStream"); m_USImageLoggingFilter->Update(); m_USImageLoggingFilter->SetImageFilesExtension(".jpg"); m_USImageLoggingFilter->SaveImages( QString(m_ExperimentResultsSubDirectory + QDir::separator() + "ImageStream" + QDir::separator()).toStdString()); m_USImageLoggingFilter = mitk::USImageLoggingFilter::New(); m_NavigationDataRecorder->StopRecording(); // Write data to csv and xml file mitk::IOUtil::Save( m_NavigationDataRecorder->GetNavigationDataSet(), (QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.xml").toStdString().c_str())); mitk::IOUtil::Save( m_NavigationDataRecorder->GetNavigationDataSet(), (QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.csv").toStdString().c_str())); // write logged navigation data messages to separate file std::stringstream csvNavigationMessagesFilename; csvNavigationMessagesFilename << m_ExperimentResultsSubDirectory.toStdString() << QDir::separator().toLatin1() - << "CSVNavigationMessagesLogFile.csv"; + << "CSVNavigationMessagesLogFile.csv"; MITK_INFO("USNavigationLogging") << "Writing logged navigation messages to separate csv file: " - << csvNavigationMessagesFilename.str(); + << csvNavigationMessagesFilename.str(); m_LoggingBackend.WriteCSVFileWithNavigationMessages(csvNavigationMessagesFilename.str()); mbilog::UnregisterBackend(&m_LoggingBackend); m_IsExperimentRunning = false; m_ImageAndNavigationDataLoggingTimer->stop(); m_CombinedModality = nullptr; // reset scene number for next experiment m_SceneNumber = 1; this->WaitCursorOff(); MITK_INFO("USNavigationLogging") << "Finished!"; } -void QmitkUSNavigationMarkerPlacement::OnCombinedModalityChanged( - itk::SmartPointer combinedModality) -{ - // remove old listener for ultrasound device changes - if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) - { - m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); - } - - m_CombinedModality = combinedModality; - m_ReinitAlreadyDone = false; - - // add a listener for ultrasound device changes - if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) - { - m_CombinedModality->GetUltrasoundDevice()->AddPropertyChangedListener(m_ListenerDeviceChanged); - } - - // update navigation data recorder for using the new combined modality - mitk::NavigationDataSource::Pointer navigationDataSource = combinedModality->GetNavigationDataSource(); - m_NavigationDataRecorder->ConnectTo(navigationDataSource); - m_NavigationDataRecorder->ResetRecording(); - - // update ultrasound image logging filter for using the new combined modality - mitk::USDevice::Pointer ultrasoundImageSource = combinedModality->GetUltrasoundDevice(); - for (unsigned int n = 0; n < ultrasoundImageSource->GetNumberOfIndexedOutputs(); ++n) - { - m_USImageLoggingFilter->SetInput(n, ultrasoundImageSource->GetOutput(n)); - } - - // update ablation zone filter for using the new combined modality - for (unsigned int n = 0; n < navigationDataSource->GetNumberOfIndexedOutputs(); ++n) - { - m_AblationZonesDisplacementFilter->SetInput(n, navigationDataSource->GetOutput(n)); - } - m_AblationZonesDisplacementFilter->SelectInput(m_MarkerIndex); - - // make sure that a reinit is done for the new images - this->ReinitOnImage(); -} - void QmitkUSNavigationMarkerPlacement::OnSettingsChanged(itk::SmartPointer settings) { - std::string applicationName; - if (!settings->GetStringProperty("settings.application", applicationName)) - { - // set default application if the string property is not available - applicationName = "Marker Placement"; - } - - // create navigation step widgets according to the selected application - if (applicationName != m_CurrentApplicationName) - { - m_CurrentApplicationName = applicationName; - - QmitkUSNavigationProcessWidget::NavigationStepVector navigationSteps; - if (applicationName == "Puncture") - { - QmitkUSNavigationStepCombinedModality* stepCombinedModality = - new QmitkUSNavigationStepCombinedModality(m_Parent); - QmitkUSNavigationStepTumourSelection* stepTumourSelection = - new QmitkUSNavigationStepTumourSelection(m_Parent); - stepTumourSelection->SetTargetSelectionOptional(true); - m_TargetNodeDisplacementFilter = stepTumourSelection->GetTumourNodeDisplacementFilter(); - QmitkUSNavigationStepZoneMarking* stepZoneMarking = - new QmitkUSNavigationStepZoneMarking(m_Parent); - QmitkUSNavigationStepPunctuationIntervention* stepIntervention = - new QmitkUSNavigationStepPunctuationIntervention(m_Parent); - - connect(stepIntervention, SIGNAL(AddAblationZoneClicked(int)), this, SLOT(OnAddAblationZone(int))); - connect(stepIntervention, SIGNAL(AblationZoneChanged(int, int)), this, SLOT(OnChangeAblationZone(int, int))); - - m_NavigationStepNames = std::vector(); - navigationSteps.push_back(stepCombinedModality); - m_NavigationStepNames.push_back("Combined Modality Initialization"); - navigationSteps.push_back(stepTumourSelection); - m_NavigationStepNames.push_back("Target Selection"); - navigationSteps.push_back(stepZoneMarking); - m_NavigationStepNames.push_back("Critical Structure Marking"); - navigationSteps.push_back(stepIntervention); - m_NavigationStepNames.push_back("Intervention"); - } - else if (applicationName == "Marker Placement") - { - QmitkUSNavigationStepCombinedModality *stepCombinedModality = new QmitkUSNavigationStepCombinedModality(m_Parent); - QmitkUSNavigationStepTumourSelection *stepTumourSelection = new QmitkUSNavigationStepTumourSelection(m_Parent); - m_TargetNodeDisplacementFilter = stepTumourSelection->GetTumourNodeDisplacementFilter(); - QmitkUSNavigationStepZoneMarking *stepZoneMarking = new QmitkUSNavigationStepZoneMarking(m_Parent); - QmitkUSNavigationStepPlacementPlanning *stepPlacementPlanning = - new QmitkUSNavigationStepPlacementPlanning(m_Parent); - QmitkUSNavigationStepMarkerIntervention *stepMarkerIntervention = - new QmitkUSNavigationStepMarkerIntervention(m_Parent); - - m_NavigationStepNames = std::vector(); - navigationSteps.push_back(stepCombinedModality); - m_NavigationStepNames.push_back("Combined Modality Initialization"); - navigationSteps.push_back(stepTumourSelection); - m_NavigationStepNames.push_back("Target Selection"); - navigationSteps.push_back(stepZoneMarking); - m_NavigationStepNames.push_back("Critical Structure Marking"); - navigationSteps.push_back(stepPlacementPlanning); - m_NavigationStepNames.push_back("Placement Planning"); - navigationSteps.push_back(stepMarkerIntervention); - m_NavigationStepNames.push_back("Marker Intervention"); - } - - // set navigation step widgets to the process widget - ui->navigationProcessWidget->SetNavigationSteps(navigationSteps); - - for (QmitkUSNavigationProcessWidget::NavigationStepIterator it = m_NavigationSteps.begin(); - it != m_NavigationSteps.end(); - ++it) - { - delete *it; - } - m_NavigationSteps.clear(); - m_NavigationSteps = navigationSteps; - } - // initialize gui according to the experiment mode setting bool experimentMode = false; settings->GetBoolProperty("settings.experiment-mode", experimentMode); ui->startExperimentButton->setVisible(experimentMode); ui->finishExperimentButton->setVisible(experimentMode); ui->runningLabel->setVisible(experimentMode); if (experimentMode && !m_IsExperimentRunning) { - ui->navigationProcessWidget->ResetNavigationProcess(); - ui->navigationProcessWidget->EnableInteraction(false); ui->runningLabel->setPixmap(m_IconNotRunning); } else if (!experimentMode) { if (m_IsExperimentRunning) { this->OnFinishExperiment(); } - ui->navigationProcessWidget->EnableInteraction(true); } // get the results directory from the settings and use home directory if // there is no results directory configured std::string resultsDirectory; if (settings->GetStringProperty("settings.experiment-results-directory", resultsDirectory)) { m_ResultsDirectory = QString::fromStdString(resultsDirectory); } else { m_ResultsDirectory = QDir::homePath(); } // make sure that the results directory exists QDir resultsDirectoryQDir = QDir(m_ResultsDirectory); if (!resultsDirectoryQDir.exists()) { resultsDirectoryQDir.mkpath(m_ResultsDirectory); } MITK_INFO("USNavigation") << "Results Directory: " << m_ResultsDirectory.toStdString(); } -void QmitkUSNavigationMarkerPlacement::OnActiveNavigationStepChanged(int index) -{ - // update navigation step timer each time the active navigation step changes - m_NavigationStepTimer->SetActiveIndex(index, m_NavigationSteps.at(index)->GetTitle().toStdString()); - if (static_cast(m_NavigationStepNames.size()) <= index) - { - MITK_INFO("USNavigationLogging") << "Someting went wrong: unknown navigation step!"; - } - else - { - MITK_INFO("USNavigationLogging") << "Navigation step finished/changed, next step: " - << this->m_NavigationStepNames.at(index).toStdString() - << "; duration until now: " << m_NavigationStepTimer->GetTotalDuration(); - } -} - -void QmitkUSNavigationMarkerPlacement::OnNextNavigationStepInitialization(int index) -{ - MITK_DEBUG << "Next Step: " << m_NavigationSteps.at(index)->GetTitle().toStdString(); - - if (m_NavigationSteps.at(index)->GetTitle().toStdString() == "Computer-assisted Intervention") - { - QmitkUSNavigationStepPunctuationIntervention* navigationStepPunctuationIntervention = static_cast(m_NavigationSteps.at(index)); - if (navigationStepPunctuationIntervention != nullptr) - { - if (m_CurrentStorage.IsNull()) { this->UpdateToolStorage(); } - if (m_CurrentStorage.IsNull() || (m_CurrentStorage->GetTool(m_NeedleIndex).IsNull())) - { - MITK_WARN << "Found null pointer when setting the tool axis, aborting"; - } - else - { - navigationStepPunctuationIntervention->SetNeedleMetaData(m_CurrentStorage->GetTool(m_NeedleIndex)); - MITK_DEBUG << "Needle axis vector: " << m_CurrentStorage->GetTool(m_NeedleIndex)->GetToolAxis(); - } - } - } -} - -void QmitkUSNavigationMarkerPlacement::OnIntermediateResultProduced(const itk::SmartPointer resultsNode) -{ - // intermediate results only matter during an experiment - if (!m_IsExperimentRunning) - { - return; - } - - this->WaitCursorOn(); - - // set results node to the experiment logging (for saving contents to the - // file system) - m_ExperimentLogging->SetResult(resultsNode); - - std::string resultsName; - if (!resultsNode->GetName(resultsName)) - { - MITK_WARN << "Could not get name of current results node."; - return; - } - - // save the mitk scene - std::string scenefile = QString(m_ExperimentResultsSubDirectory + QDir::separator() + - QString("Scene %1 - ").arg(m_SceneNumber++, 2, 10, QChar('0')) + - QString::fromStdString(resultsName).replace(":", "_") + ".mitk") - .toStdString(); - MITK_INFO << "Saving Scene File: " << scenefile; - - mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New(); - 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); - - this->Convert2DImagesTo3D(nodesToBeSaved); - - sceneIO->SaveScene(nodesToBeSaved, this->GetDataStorage(), scenefile); - - this->WaitCursorOff(); -} - void QmitkUSNavigationMarkerPlacement::ReinitOnImage() { if (!m_ReinitAlreadyDone && m_CombinedModality.IsNotNull()) { // make sure that the output is already calibrated correctly // (if the zoom level was changed recently) m_CombinedModality->Modified(); m_CombinedModality->Update(); mitk::Image::Pointer image = m_CombinedModality->GetOutput(); if (image.IsNotNull() && image->IsInitialized()) { // make a reinit on the ultrasound image mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); if (renderWindow != NULL && image->GetTimeGeometry()->IsValid()) { renderWindow->GetRenderingManager()->InitializeViews( image->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); renderWindow->GetRenderingManager()->RequestUpdateAll(); } this->RequestRenderWindowUpdate(); m_ReinitAlreadyDone = true; } } } void QmitkUSNavigationMarkerPlacement::Convert2DImagesTo3D(mitk::DataStorage::SetOfObjects::ConstPointer nodes) { for (mitk::DataStorage::SetOfObjects::ConstIterator it = nodes->Begin(); it != nodes->End(); ++it) { if (it->Value()->GetData() && strcmp(it->Value()->GetData()->GetNameOfClass(), "Image") == 0) { // convert image to 3d image if it is 2d at the moment mitk::Image::Pointer image = dynamic_cast(it->Value()->GetData()); if (image.IsNotNull() && image->GetDimension() == 2 && !image->GetGeometry()->Is2DConvertable()) { mitk::Convert2Dto3DImageFilter::Pointer convert2DTo3DImageFilter = mitk::Convert2Dto3DImageFilter::New(); convert2DTo3DImageFilter->SetInput(image); convert2DTo3DImageFilter->Update(); it->Value()->SetData(convert2DTo3DImageFilter->GetOutput()); } } } } void QmitkUSNavigationMarkerPlacement::CreateOverlays() { // initialize warning overlay (and do not display it, yet) m_WarnOverlay->SetText("Warning: No calibration available for current depth."); // set position and font size for the text overlay // (nonesense postition as a layouter is used, but it ignored // the overlay without setting a position here) mitk::Point2D overlayPosition; overlayPosition.SetElement(0, -50.0f); overlayPosition.SetElement(1, -50.0f); m_WarnOverlay->SetPosition2D(overlayPosition); m_WarnOverlay->SetFontSize(22); m_WarnOverlay->SetColor(1, 0, 0); // overlay should be red } void QmitkUSNavigationMarkerPlacement::UpdateToolStorage() { - if (m_NavigationDataSource.IsNull()) { m_NavigationDataSource = m_CombinedModality->GetNavigationDataSource(); } - if (m_NavigationDataSource.IsNull()) { MITK_WARN << "Found an invalid navigation data source object!"; } - us::ModuleContext* context = us::GetModuleContext(); + if (m_NavigationDataSource.IsNull()) + { + m_NavigationDataSource = m_CombinedModality->GetNavigationDataSource(); + } + if (m_NavigationDataSource.IsNull()) + { + MITK_WARN << "Found an invalid navigation data source object!"; + } + us::ModuleContext *context = us::GetModuleContext(); std::string id = m_NavigationDataSource->US_PROPKEY_ID; std::string filter = "(" + mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID + "=" + id + ")"; // Get Storage - std::vector > refs = context->GetServiceReferences(); + std::vector> refs = + context->GetServiceReferences(); m_CurrentStorage = context->GetService(refs.front()); if (m_CurrentStorage.IsNull()) { MITK_WARN << "Found an invalid storage object!"; } - else if (m_CurrentStorage->GetToolCount() != m_NavigationDataSource->GetNumberOfOutputs()) //there is something wrong with the storage + else if (m_CurrentStorage->GetToolCount() != + m_NavigationDataSource->GetNumberOfOutputs()) // there is something wrong with the storage { - MITK_WARN << "Found a tool storage, but it has not the same number of tools like the NavigationDataSource. This storage won't be used because it isn't the right one."; + MITK_WARN << "Found a tool storage, but it has not the same number of tools like the NavigationDataSource. This " + "storage won't be used because it isn't the right one."; m_CurrentStorage = NULL; } } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationMarkerPlacement.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.h similarity index 84% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationMarkerPlacement.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.h index e4e4634543..d2a811e5be 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationMarkerPlacement.h +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.h @@ -1,216 +1,213 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkUSNAVIGATIONMARKERPLACEMENT_H #define QmitkUSNAVIGATIONMARKERPLACEMENT_H #include #include "IO/mitkUSNavigationLoggingBackend.h" -#include "Widgets/QmitkUSNavigationProcessWidget.h" #include "mitkNavigationDataRecorder.h" #include "mitkNodeDisplacementFilter.h" #include "mitkUSImageLoggingFilter.h" #include #include -#include +#include #include +#include namespace itk { template class SmartPointer; } namespace mitk { class USNavigationStepTimer; - class USNavigationExperimentLogging; } namespace Ui { class QmitkUSNavigationMarkerPlacement; } class QmitkUSAbstractNavigationStep; class QmitkUSNavigationStepPunctuationIntervention; class QmitkStdMultiWidget; class QTimer; class QSignalMapper; /** * \brief View for navigated marker placement using the combined modality. * This view utilizes the QmitkUSNavigationProcessWidget to do the navigation * process. It can be switched between widgets for marker placement and widgets * for punctuation. * * An experiment mode allows for logging results, durations and the ultrasound * images. */ class QmitkUSNavigationMarkerPlacement : public QmitkAbstractView { Q_OBJECT protected slots: + + void OnGetCursorPosition(); + void OnActualizeCtToUsRegistrationWidget(); + void OnInitializeCtToUsRegistration(); + void OnInitializeTargetMarking(); + void OnInitializeCriticalStructureMarking(); + void OnInitializeNavigation(); + /** * \brief Called periodically to update the rendering. * The standard multi widget is changed to fit the navigation process once it * is available and a reinit on the ultrasound image is done for a new image * node. */ void OnTimeout(); /** * \brief Called periodically during an experiment for logging the ultrasound images. */ void OnImageAndNavigationDataLoggingTimeout(); /** * \brief Initializes anything neccessary for an experiment. * The user is asked for a directory for storing the results and the logging * is started. */ void OnStartExperiment(); /** * \brief Stops logging and saves everything to the file system. */ void OnFinishExperiment(); - void OnCombinedModalityChanged(itk::SmartPointer); - /** * \brief Switches the navigation step widgets if the navigation application was changed. */ void OnSettingsChanged(itk::SmartPointer); - /** - * \brief Updates the timer for the navigation steps durations every time the active navigation step changes. - */ - void OnActiveNavigationStepChanged(int); - - /** Initializes the next navigation step */ - void OnNextNavigationStepInitialization(int); - - /** - * \brief The data node is given to the experiment logging and scene is saved to the file system. - */ - void OnIntermediateResultProduced(const itk::SmartPointer); - void OnAddAblationZone(int size); void OnEnableNavigationLayout(); void OnResetStandardLayout(); void OnChangeLayoutClicked(); void OnChangeAblationZone(int id, int newSize); void OnRenderWindowSelection(); void OnRefreshView(); public: static const char *DATANAME_TUMOUR; static const char *DATANAME_TARGETSURFACE; static const char *DATANAME_ZONES; static const char *DATANAME_TARGETS; static const char *DATANAME_TARGETS_PATHS; static const char *DATANAME_REACHED_TARGETS; explicit QmitkUSNavigationMarkerPlacement(); ~QmitkUSNavigationMarkerPlacement(); virtual void CreateQtPartControl(QWidget *parent); static const std::string VIEW_ID; void OnCombinedModalityPropertyChanged(const std::string &, const std::string &); protected: /** * \brief A reinit on the ultrasound image is performed every time the view gets the focus. */ virtual void SetFocus(); /** * \brief Helper function which performs a reinit on the ultrasound image. */ void ReinitOnImage(); /** * \brief Sets the multiwidget to two windows, axial on top and 3D render window on the bottom. */ virtual void SetTwoWindowView(); /** * \brief Helper function for being able to serialize the 2d ultrasound image. */ void Convert2DImagesTo3D(mitk::DataStorage::SetOfObjects::ConstPointer nodes); + void ReInitializeSettingsNodesAndImageStream(); + void UpdateToolStorage(); void CreateOverlays(); + void InitImageStream(); + QWidget *m_Parent; - QmitkUSNavigationProcessWidget::NavigationStepVector m_NavigationSteps; QTimer *m_UpdateTimer; QTimer *m_ImageAndNavigationDataLoggingTimer; QmitkStdMultiWidget *m_StdMultiWidget; - itk::SmartPointer m_CombinedModality; + itk::SmartPointer m_CombinedModality; + itk::SmartPointer m_SettingsNode; bool m_ReinitAlreadyDone; bool m_IsExperimentRunning; std::string m_CurrentApplicationName; - itk::SmartPointer m_NavigationStepTimer; - itk::SmartPointer m_ExperimentLogging; QPixmap m_IconRunning; QPixmap m_IconNotRunning; QString m_ResultsDirectory; QString m_ExperimentName; QString m_ExperimentResultsSubDirectory; std::vector m_NavigationStepNames; // stores the names of the navigation steps which are currently used (for logging purposes) mitk::USNavigationLoggingBackend m_LoggingBackend; mitk::USImageLoggingFilter::Pointer m_USImageLoggingFilter; mitk::NavigationDataRecorder::Pointer m_NavigationDataRecorder; // records navigation data files mitk::NodeDisplacementFilter::Pointer m_TargetNodeDisplacementFilter; mitk::NodeDisplacementFilter::Pointer m_AblationZonesDisplacementFilter; + mitk::NavigationDataObjectVisualizationFilter::Pointer m_ToolVisualizationFilter; + mitk::DataNode::Pointer m_InstrumentNode; std::vector m_AblationZonesVector; int m_NeedleIndex; int m_MarkerIndex; int m_SceneNumber; itk::SmartPointer m_WarnOverlay; //To get tool storage mitk::NavigationDataSource::Pointer m_NavigationDataSource; mitk::NavigationToolStorage::Pointer m_CurrentStorage; -private: - mitk::MessageDelegate2 m_ListenerDeviceChanged; + itk::SmartPointer m_BaseNode; + itk::SmartPointer m_ImageStreamNode; +private: Ui::QmitkUSNavigationMarkerPlacement *ui; }; #endif // USNAVIGATIONMARKERPLACEMENT_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.ui new file mode 100644 index 0000000000..8fc3e3dbaf --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.ui @@ -0,0 +1,282 @@ + + + QmitkUSNavigationMarkerPlacement + + + + 0 + 0 + 562 + 446 + + + + Form + + + + + + true + + + 1 + + + + Initialization + + + + + + + + + + Navigation Control + + + + + + 0 + + + + + 0 + 0 + 520 + 257 + + + + CT-to-US Registration + + + + + + Initialize + + + + + + + + + + + + 0 + 0 + 98 + 57 + + + + Target + + + + + + Initialize + + + + + + + + + + + + 0 + 0 + 98 + 57 + + + + Critical Structures + + + + + + Initialize + + + + + + + + + + + + 0 + 0 + 98 + 57 + + + + Needle Insertion + + + + + + Initialize + + + + + + + + + + + + + + + Settings + + + + + + + + + Qt::Horizontal + + + + + + + + + Enable Navigation Render Window Layout with RenderWindow + + + true + + + + + + + 1 + + + 3 + + + + + + + Refresh view + + + + + + + + + Qt::Horizontal + + + + + + + false + + + Finish Experiment + + + + + + + Start New Experiment + + + + + + + + + + + + 20 + 20 + + + + + + + + + + + + QmitkUSNavigationStepCombinedModality + QWidget +
src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h
+ 1 +
+ + QmitkUSNavigationStepTumourSelection + QWidget +
src/internal/NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.h
+ 1 +
+ + QmitkUSNavigationStepZoneMarking + QWidget +
src/internal/NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.h
+ 1 +
+ + QmitkUSNavigationStepPunctuationIntervention + QWidget +
src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h
+ 1 +
+ + QmitkUSNavigationCombinedSettingsWidget + QWidget +
src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.h
+ 1 +
+ + QmitkUSNavigationStepCtUsRegistration + QWidget +
src/internal/NavigationStepWidgets/QmitkUSNavigationStepCtUsRegistration.h
+ 1 +
+
+ + + + OnStartExperiment() + OnFinishExperiment() + +
diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationPerspective.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationPerspective.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationPerspective.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationPerspective.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationPerspective.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationPerspective.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationPerspective.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationPerspective.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationZoneDistancesWidget.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationZoneDistancesWidget.ui similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSNavigationZoneDistancesWidget.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationZoneDistancesWidget.ui diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSZoneManagementColorDialogDelegate.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSZoneManagementColorDialogDelegate.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSZoneManagementColorDialogDelegate.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSZoneManagementColorDialogDelegate.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSZoneManagementColorDialogDelegate.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSZoneManagementColorDialogDelegate.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSZoneManagementColorDialogDelegate.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSZoneManagementColorDialogDelegate.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSZonesDataModel.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSZonesDataModel.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSZonesDataModel.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSZonesDataModel.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSZonesDataModel.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSZonesDataModel.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUSZonesDataModel.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSZonesDataModel.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibration.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUltrasoundCalibration.cpp similarity index 93% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibration.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUltrasoundCalibration.cpp index e817742768..89b696a60e 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibration.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUltrasoundCalibration.cpp @@ -1,1155 +1,1164 @@ /*=================================================================== 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, "OnDeviceServiceEvent", 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); + m_CalibNode->SetData(this->m_CalibPointsTool); 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); + m_WorldNode->SetData(this->m_CalibPointsImage); this->GetDataStorage()->Add(m_WorldNode); m_CombinedModality = m_Controls.m_CombinedModalityManagerWidget->GetSelectedCombinedModality(); + m_CombinedModality->SetCalibration(mitk::AffineTransform3D::New()); //dummy calibration because without a calibration the comined modality was laggy (maybe a bug?) 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->GetDeviceState() < mitk::USDevice::State_Connected) { m_CombinedModality->Connect(); } - if (m_CombinedModality->GetDeviceState() < mitk::USDevice::State_Activated) { m_CombinedModality->Activate(); } + 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(); + //Trigger the ProbeChanged method for initializing/updating the spacing of the ultrasound image correctly + std::string probeName = m_CombinedModality->GetUltrasoundDevice()->GetCurrentProbe()->GetName(); + m_CombinedModality->GetUltrasoundDevice()->ProbeChanged(probeName); + + mitk::DataNode::Pointer usNode = this->GetDataStorage()->GetNamedNode("US Viewing Stream - Image 0"); + if (usNode.IsNotNull()) + { + this->GetDataStorage()->Remove(usNode); + } + // 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->SetName("USTrackingNavigation 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->SetName("USTrackingNavigation 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->GetTrackingDevice()); + 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::OnDeviceServiceEvent(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()) + + if( !m_CombinedModality->GetIsTrackedUltrasoundActive() ) { - transform->SetModeToSimilarity(); - } //use affine transform + if (m_Controls.m_ScaleTransform->isChecked()) + { + transform->SetModeToSimilarity(); + } //use affine transform + else + { + transform->SetModeToRigidBody(); + } //use similarity transform: scaling is not touched + MITK_INFO << "TEST"; + } else { - transform->SetModeToRigidBody(); - } //use similarity transform: scaling is not touched + 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::AffineTransform3D::Pointer oldUSImageTransform = m_CombinedModality->GetUltrasoundDevice()->GetOutput()->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); } + if( !m_CombinedModality->GetIsTrackedUltrasoundActive() ) + { + if( !m_Controls.m_ScaleTransform->isChecked() ) { m_Transformation->Compose(oldUSImageTransform); } + MITK_INFO << "Used old USImageTransform"; + } + 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 + + + /* + if (m_Image.IsNotNull() && m_Image->IsInitialized()) + { + m_Node->SetData(m_Image); + } + else + { + m_Image = m_CombinedModality->GetOutput(); + m_Node->SetData(m_Image); + }*/ + m_CombinedModality->Modified(); m_CombinedModality->Update(); - mitk::Image::Pointer m_Image = m_CombinedModality->GetOutput(); - if (m_Image.IsNotNull() && m_Image->IsInitialized()) + + // Update US Image + mitk::Image::Pointer image = m_CombinedModality->GetOutput(); + // make sure that always the current image is set to the data node + if (image.IsNotNull() && m_Node->GetData() != image.GetPointer() && image->IsInitialized()) { - if (m_OverrideSpacing) - { - m_Image->GetGeometry()->SetSpacing(m_Spacing); - } - if (m_Image.IsNotNull() && m_Image->IsInitialized()) - { - m_Node->SetData(m_Image); - } + m_Node->SetData(image); } // Update Needle Projection m_NeedleProjectionFilter->Update(); //only update 2d window because it is faster - //this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); + 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(); + 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->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->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->GetIsFreezed()) { - if (!m_Timer->isActive()) // Activate Imaging - { - // if (m_Node) m_Node->ReleaseData(); - if (m_CombinedModality.IsNull()) { - m_Timer->stop(); - return; - } - m_Timer->start(); - } - //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->SetIsFreezed(false); - } else { - //deactivate Imaging - m_Timer->stop(); - m_CombinedModality->SetIsFreezed(true); m_Controls.m_SpacingAddPoint->setEnabled(true); } - //SwitchFreeze(); + 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; + m_CombinedModality->GetUltrasoundDevice()->SetSpacing(xSpacing, ySpacing); //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->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/QmitkUltrasoundCalibration.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUltrasoundCalibration.h similarity index 96% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibration.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUltrasoundCalibration.h index a248221248..5936aec4b6 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibration.h +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUltrasoundCalibration.h @@ -1,348 +1,344 @@ /*=================================================================== 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 QmitkUltrasoundCalibration_h #define QmitkUltrasoundCalibration_h #include #include //QT //#include //MITK #include #include #include #include #include #include // Microservices #include "ui_QmitkUltrasoundCalibrationControls.h" #include #include #include #include /*! \brief QmitkUltrasoundCalibration \warning This view provides a simple calibration process. \sa QmitkFunctionality \ingroup ${plugin_target}_internal */ class QmitkUltrasoundCalibration : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: QmitkUltrasoundCalibration(); ~QmitkUltrasoundCalibration(); static const std::string VIEW_ID; virtual void CreateQtPartControl(QWidget *parent); void OnUSDepthChanged(const std::string&, const std::string&); protected slots: /** * \brief Triggered, whenever the user switches Tabs * */ void OnTabSwitch(int index); /** * \brief Triggered, when the user has clicked "select Devices". * */ //void OnSelectDevice(mitk::USCombinedModality::Pointer); void OnDeviceSelected(); void OnDeviceDeselected(); /** * \brief Triggered, when the user clicks "Add Point" * */ void OnAddCalibPoint(); /** * \brief Triggered, when the user clicks "Calibrate" * */ void OnCalibration(); /** * \brief Triggered, when the user clicks "Add Target Points". * * Adds an image point and an tracking point to their respective evaluation pointsets */ void OnAddEvalTargetPoint(); /** * \brief Triggered, when the user clicks "Add Point". * * Adds a projected point to the projected point evaluation set. */ void OnAddEvalProjectedPoint(); /** * \brief Triggered when the user clicks "Save Results" in the Evaluation tab. */ void OnSaveEvaluation(); /** * \brief Triggered when the user clicks "Save Calibration" in the Calibration tab. */ void OnSaveCalibration(); /** * \brief Triggered when the user clicks "Run Next Round". Also used as a reset mechanism. */ void OnReset(); /** * \brief Triggered in regular intervals by a timer, when live view is enabled. * */ void Update(); /** * \brief Freezes or unfreezes the image. */ void SwitchFreeze(); /** * */ void OnStartCalibrationProcess(); /** - *\brief Method to use the PLUS-Toolkoit for Calibration of EchoTrack + *\brief Method to use the PLUS-Toolkoit for Calibration of USTrackingNavigation */ void OnStartPlusCalibration(); void OnStopPlusCalibration(); /** *\ brief Starts the Streaming of USImage and Navigation Data when PLUS is connected */ void OnStartStreaming(); void OnNewConnection(); /** \*brief Get the Calibration from the PLUS-Toolkit once Calibration with fCal is done */ void OnGetPlusCalibration(); /** \*brief Convert the recieved igtl::Matrix into an mitk::AffineTransform3D which can be used to calibrate the CombinedModality */ void ProcessPlusCalibration(igtl::Matrix4x4& imageToTracker); void OnStreamingTimerTimeout(); /** * */ void OnStopCalibrationProcess(); void OnAddCurrentTipPositionToReferencePoints(); void OnStartVerification(); void OnAddCurrentTipPositionForVerification(); void OnDeviceServiceEvent(const ctkServiceEvent event); void OnFreezeClicked(); void OnAddSpacingPoint(); void OnCalculateSpacing(); signals: /** * \brief used for thread seperation, the worker thread must not call OnNewConnection directly. * QT signals are thread safe and separate the threads */ void NewConnectionSignal(); protected: virtual void SetFocus(); /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer source, const QList& nodes); Ui::QmitkUltrasoundCalibrationControls m_Controls; /** * \brief Internal function that activates display of the needle path. */ void ShowNeedlePath(); /** * \brief Clears all member attributes which are holding intermediate results for the calibration. */ void ClearTemporaryMembers(); void OnPlusConnected(); /** * \brief The combined modality used for imaging and tracking. */ - mitk::USCombinedModality::Pointer m_CombinedModality; + mitk::AbstractUltrasoundTrackerDevice::Pointer m_CombinedModality; /** * \brief NavigationDataSource used for tracking data. * This will be gotten by the combined modality. */ mitk::NavigationDataSource::Pointer m_Tracker; QTimer *m_Timer; mitk::DataNode::Pointer m_Node; mitk::DataNode::Pointer m_CalibNode; mitk::DataNode::Pointer m_WorldNode; //IGTL Servers and Devices needed for the communication with PLUS mitk::IGTLServer::Pointer m_USServer; mitk::IGTLMessageProvider::Pointer m_USMessageProvider; mitk::ImageToIGTLMessageFilter::Pointer m_USImageToIGTLMessageFilter; mitk::IGTLServer::Pointer m_TrackingServer; mitk::IGTLMessageProvider::Pointer m_TrackingMessageProvider; mitk::NavigationDataToIGTLMessageFilter::Pointer m_TrackingToIGTLMessageFilter; mitk::IGTLClient::Pointer m_TransformClient; mitk::IGTLDeviceSource::Pointer m_TransformDeviceSource; QTimer *m_StreamingTimer; unsigned long m_NewConnectionObserverTag; - // Variables to determine if spacing was calibrated and needs to be applied to the incoming images - mitk::Vector3D m_Spacing; - bool m_OverrideSpacing; - /** * \brief The current Ultrasound Image. */ mitk::Image::Pointer m_Image; /** * \brief Current point when the image was last frozen. */ mitk::Point3D m_FreezePoint; /** * \brief Pointset containing all tool points. */ mitk::PointSet::Pointer m_CalibPointsImage; /** * \brief Pointset containing corresponding points on the image. */ mitk::PointSet::Pointer m_CalibPointsTool; /** * \brief Pointset containing Projected Points (aka "where we thought the needle was gonna land") */ mitk::PointSet::Pointer m_EvalPointsProjected; /** * \brief Pointset containing the evaluated points on the image. */ mitk::PointSet::Pointer m_EvalPointsImage; /** * \brief Pointset containing tracked evaluation points. */ mitk::PointSet::Pointer m_EvalPointsTool; /** * \brief Pointset containing tracked evaluation points. */ mitk::PointSet::Pointer m_VerificationReferencePoints; mitk::DataNode::Pointer m_VerificationReferencePointsDataNode; int m_currentPoint; std::vector m_allReferencePoints; std::vector m_allErrors; /** * \brief Pointset containing points along the needle's prohected path. Only used for visualization. The first point is the needle tip. */ //mitk::PointSet::Pointer m_NeedlePathPoints; /** * \brief Creates a Pointset that projects the needle's path */ mitk::NeedleProjectionFilter::Pointer m_NeedleProjectionFilter; /** * \brief Total number of calibration points set. */ int m_CalibPointsCount; QString m_CurrentDepth; /** * \brief StatisticsRegarding Projection Accuracy. * (Compares m_EvalPointsProjected to m_EvalPointsImage) */ mitk::PointSetDifferenceStatisticsCalculator::Pointer m_ProjectionStatistics; /** * \brief StatisticsRegarding Evaluation Accuracy. * (Compares m_EvalPointsTool to m_EvalPointsImage) */ mitk::PointSetDifferenceStatisticsCalculator::Pointer m_EvaluationStatistics; /** * \brief StatisticsRegarding Calibration Accuracy. * (Compares m_CalibPointsTool to a transformed copy of m_CalibPointsImage). */ mitk::PointSetDifferenceStatisticsCalculator::Pointer m_CalibrationStatistics; /** * \brief Result of the Calibration. */ mitk::AffineTransform3D::Pointer m_Transformation; /** * This method is copied from PointSetModifier which is part of MBI. It should be replaced * by external method call as soon as this functionality will be available in MITK. */ vtkSmartPointer ConvertPointSetToVtkPolyData(mitk::PointSet::Pointer PointSet); double ComputeFRE(mitk::PointSet::Pointer imageFiducials, mitk::PointSet::Pointer realWorldFiducials, vtkSmartPointer transform = nullptr); void ApplyTransformToPointSet(mitk::PointSet::Pointer pointSet, vtkSmartPointer transform); mitk::PointSet::Pointer m_SpacingPoints; mitk::DataNode::Pointer m_SpacingNode; int m_SpacingPointsCount; private: mitk::MessageDelegate2 m_USDeviceChanged; }; #endif // UltrasoundCalibration_h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibrationControls.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUltrasoundCalibrationControls.ui similarity index 98% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibrationControls.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUltrasoundCalibrationControls.ui index cfd6e837aa..c5dbcbd640 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibrationControls.ui +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUltrasoundCalibrationControls.ui @@ -1,959 +1,959 @@ QmitkUltrasoundCalibrationControls true 0 0 374 923 0 0 QmitkTemplate 0 0 - 2 + 1 0 0 - 362 - 388 + 356 + 369 Config false Start Calibration for Selected Device 0 0 - 362 - 388 + 340 + 681 Spatial Calibration - 0 + 2 Spacing <html><head/><body><p>1. Freeze the US-Image.</p><p>2. Mark two points in the US-Image of which you know <br/>they are exactly 30mm apart in horizontal direction.</p><p>3. Marktwo more points in the US-Image of which you <br/>know they are exactly 20mm apart vertical direction.</p><p>4. Now you can click the &quot;Calculate Spacing&quot;-Button. <br/>The spacing is calculated and applied to the US-Image.</p></body></html> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Add Point Qt::Horizontal QSizePolicy::Expanding 40 20 false Freeze Calculate Spacing Point Based <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; text-decoration: underline;">Step 1: Collect Points</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Slowly move a tracking tool into the image plane of the ultrasound. As soon as it becomes visible, click &quot;freeze&quot; and mark the point on the screen by moving the Crosshair to the pont in the US image (best: click in 2D Axial view).</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Do this with as many points as necessary, then click calibrate to perform calibration.</p></body></html> true 75 true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Tracking Status:</span></p></body></html> 0 40 Freeze Qt::Horizontal 40 20 false Add Point Qt::Horizontal <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; text-decoration: underline;">Step 2: Calibrate (perform landmark transformation)</span></p></body></html> Activate Scaling during Calibration Transform Calibrate Qt::Horizontal <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; text-decoration: underline;">Step 3: Save calibration to hard disc</span></p></body></html> Save additional logging information (MITK scene, etc.) true false Save Calibration Qt::Horizontal Stop Calibration Process Restart Current Calibration PLUS Connection false false Setup PLUS Connection false false Start Streaming false Get Calibration from PLUS false Save PLUS Calibration Stop Calibration with PLUS <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Step 1: Calibrate using fCal</span></p></body></html> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">1. Setup the Connection to PLUS</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">2. Start fCal with the EchoTrackCalibration Config file</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">2. Start fCal with the USTrackingNavigationCalibration Config file</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">3. Connect fcal to MITK, once it connected successfully you can click the &quot;Start Streaming&quot; Button below</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">4. Now follow the steps in fCal and don't forget to save the Calibration in the end</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">5. Finish fCal</p></body></html> true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Step 2: Get the calibration back from PLUS</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">1. Start a PLUS Server with the configfile you saved in the final step of fCal</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">2. Once the Server connected to MITK click the &quot;Start Streaming&quot; Button below</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">3. Now Click the &quot;Get Calibration from PLUS&quot;Button below</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">4. You can now save the calibration</p></body></html> true Qt::Vertical 20 40 Qt::Vertical 20 40 0 0 - 352 - 411 + 339 + 527 Evaluation 0 Point Based Evaluation <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Bring the needle into the tracking volume, so the projection can be calculated</span></p></body></html> true Step 1: Save Needle Projection Push the needle forward until it becomes visible in the Image true Step 2: Freeze Image Mark the visible needle tip with the crosshair Step 3: Add Target Points When done, save results Run Next Round Prefix: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Save Results Path: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Control QFormLayout::AllNonFixedFieldsGrow Tracking Status: # Projection Points: # Target Points: 0 Evaluation TRE: 0 Projection TRE: 0 Calibration FRE: 0 0 Qt::Vertical 20 40 Reference Device Choose pointer: 0 50 0 0 0 - 334 - 230 + 179 + 82 Create Reference Current reference points: Add Current Pointer Tip Position Qt::Vertical 20 111 0 0 - 334 - 269 + 140 + 220 Quick Verification Start Verification Current Point: Qt::Horizontal 40 20 <none> Add current pointer tip Result: Qt::Vertical 20 40 QmitkToolTrackingStatusWidget QWidget
QmitkToolTrackingStatusWidget.h
1
QmitkUSNavigationStepCombinedModality QWidget
src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h
1
QmitkPointListWidget QWidget
QmitkPointListWidget.h
1
QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkNavigationDataSourceSelectionWidget QWidget
QmitkNavigationDataSourceSelectionWidget.h
1
OnStartCalibrationProcess() OnReset() OnStopCalibrationProcess()
diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/SettingsWidgets/QmitkUSNavigationAbstractSettingsWidget.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/SettingsWidgets/QmitkUSNavigationAbstractSettingsWidget.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/SettingsWidgets/QmitkUSNavigationAbstractSettingsWidget.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/SettingsWidgets/QmitkUSNavigationAbstractSettingsWidget.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/SettingsWidgets/QmitkUSNavigationAbstractSettingsWidget.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/SettingsWidgets/QmitkUSNavigationAbstractSettingsWidget.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/SettingsWidgets/QmitkUSNavigationAbstractSettingsWidget.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/SettingsWidgets/QmitkUSNavigationAbstractSettingsWidget.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.h index 4b18edce98..0150da4b10 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.h +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.h @@ -1,53 +1,53 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKUSNAVIGATIONCOMBINEDSETTINGSWIDGET_H #define QMITKUSNAVIGATIONCOMBINEDSETTINGSWIDGET_H #include "QmitkUSNavigationAbstractSettingsWidget.h" #include "mitkDataNode.h" namespace Ui { class QmitkUSNavigationCombinedSettingsWidget; } /** * \brief Settings widget for the USNavigationMarkerPlacement. * This widgets allows for configuring the experiment mode and for changing the * application between marker placement and punctuation. */ class QmitkUSNavigationCombinedSettingsWidget : public QmitkUSNavigationAbstractSettingsWidget { Q_OBJECT protected slots: void OnApplicationChanged(int); public: explicit QmitkUSNavigationCombinedSettingsWidget(QWidget *parent = 0); ~QmitkUSNavigationCombinedSettingsWidget(); + virtual void OnSetSettingsNode(itk::SmartPointer settingsNode, bool overwriteValues); protected: - virtual void OnSetSettingsNode(itk::SmartPointer settingsNode, bool overwriteValues); virtual void OnSaveProcessing(); virtual void OnLoadSettingsProcessing(); QString InteractionNameToFile(const QString& name) const; private: Ui::QmitkUSNavigationCombinedSettingsWidget *ui; }; #endif // QMITKUSNAVIGATIONCOMBINEDSETTINGSWIDGET_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.ui similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.ui diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigation.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/USNavigation.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigation.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/USNavigation.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigation.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/USNavigation.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigation.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/USNavigation.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationControls.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/USNavigationControls.ui similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationControls.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/USNavigationControls.ui diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/USNavigationMarkerPlacement.ui similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/USNavigationMarkerPlacement.ui diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.cpp similarity index 82% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.cpp index 62955187e3..f93de764c0 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.cpp @@ -1,81 +1,92 @@ /*=================================================================== 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 "QmitkUSCombinedModalityCreationWidget.h" #include "ui_QmitkUSCombinedModalityCreationWidget.h" +#include "mitkTrackedUltrasound.h" + QmitkUSCombinedModalityCreationWidget::QmitkUSCombinedModalityCreationWidget(QWidget *parent) : QWidget(parent), ui(new Ui::QmitkUSCombinedModalityCreationWidget) { ui->setupUi(this); std::string filterExcludeCombinedModalities = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice)(!(" + mitk::USDevice::GetPropertyKeys().US_PROPKEY_CLASS + "=" + mitk::USCombinedModality::DeviceClassIdentifier + ")))"; connect(ui->usDevicesServiceList, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(OnSelectedUltrasoundOrTrackingDevice())); connect(ui->trackingDevicesServiceList, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(OnSelectedUltrasoundOrTrackingDevice())); ui->usDevicesServiceList->SetAutomaticallySelectFirstEntry(true); ui->trackingDevicesServiceList->SetAutomaticallySelectFirstEntry(true); ui->usDevicesServiceList->Initialize(mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL, filterExcludeCombinedModalities); ui->trackingDevicesServiceList->Initialize(mitk::NavigationDataSource::US_PROPKEY_DEVICENAME); connect(ui->createButton, SIGNAL(clicked()), this, SLOT(OnCreation())); connect(ui->cancelButton, SIGNAL(clicked()), this, SIGNAL(SignalAborted())); } QmitkUSCombinedModalityCreationWidget::~QmitkUSCombinedModalityCreationWidget() { delete ui; } void QmitkUSCombinedModalityCreationWidget::OnCreation() { mitk::USDevice::Pointer usDevice = ui->usDevicesServiceList->GetSelectedService(); if (usDevice.IsNull()) { MITK_WARN << "No Ultrasound Device selected for creation of Combined Modality."; return; } mitk::NavigationDataSource::Pointer trackingDevice = ui->trackingDevicesServiceList->GetSelectedService(); if (trackingDevice.IsNull()) { MITK_WARN << "No Traccking Device selected for creation of Combined Modality."; return; } QString vendor = ui->vendorLineEdit->text(); QString name = ui->nameLineEdit->text(); - if (name.isEmpty()) { name = "Combined Modality"; } + if (name.isEmpty()) { name = "Ultrasound Tracker Device"; } + + if( ui->activateTrackedUSCheckbox->isChecked() ) + { + m_CombinedModality = mitk::TrackedUltrasound::New(usDevice, trackingDevice, true); + MITK_INFO << "Created TrackedUltrasound device"; + } + else + { + m_CombinedModality = mitk::USCombinedModality::New(usDevice, trackingDevice, false); + MITK_INFO << "Created CombinedModality device"; + } - mitk::USCombinedModality::Pointer combinedModality = mitk::USCombinedModality::New( - usDevice, trackingDevice, vendor.toStdString(), name.toStdString()); - combinedModality->Initialize(); - combinedModality->RegisterAsMicroservice(); // register as micro service + m_CombinedModality->GetUltrasoundDevice()->Initialize(); + m_CombinedModality->RegisterAsMicroservice(); // register as micro service emit SignalCreated(); - emit SignalCreated(combinedModality); + //emit SignalCreated(m_CombinedModality); } void QmitkUSCombinedModalityCreationWidget::OnSelectedUltrasoundOrTrackingDevice() { // create button is enabled only if an ultrasound // and a tracking device is selected ui->createButton->setEnabled( ui->usDevicesServiceList->GetIsServiceSelected() && ui->trackingDevicesServiceList->GetIsServiceSelected()); } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.h similarity index 96% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.h index f98b4f8e65..1b43d5ea25 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.h +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.h @@ -1,62 +1,64 @@ /*=================================================================== 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 QMITKUSCOMBINEDMODALITYCREATIONWIDGET_H #define QMITKUSCOMBINEDMODALITYCREATIONWIDGET_H #include #include "mitkUSCombinedModality.h" namespace Ui { class QmitkUSCombinedModalityCreationWidget; } /** * \brief Widget that enables the user to create a mitk::USCombinedModality of a mitk::NavigationDataSource and a mitk::USDevice. * A mitk::NavigationDataSource and a mitk::USDevice can be picked from two lists, showing * the corresponding micro service objects. The combined modality is registered as a micro * service as well during the creation process. */ class QmitkUSCombinedModalityCreationWidget : public QWidget { Q_OBJECT signals: /** \brief Emmited when the user clicks the "Cancel" button. */ void SignalAborted(); /** \brief Emmited when the user clicked the "Create" button and the creation is successfull. */ void SignalCreated(mitk::USCombinedModality::Pointer combinedModality); /** \brief Emmited when the user clicked the "Create" button and the creation is successfull. */ void SignalCreated(); protected slots: /** \brief Creates a combined modility of the selected mitk::NavigationDataSource and mitk::USDevice. **/ void OnCreation(); /** \brief Handles the enabled state of the "Create" button. **/ void OnSelectedUltrasoundOrTrackingDevice(); public: explicit QmitkUSCombinedModalityCreationWidget(QWidget *parent = 0); ~QmitkUSCombinedModalityCreationWidget(); private: Ui::QmitkUSCombinedModalityCreationWidget *ui; + + itk::SmartPointer m_CombinedModality; }; #endif // QMITKUSCOMBINEDMODALITYCREATIONWIDGET_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.ui similarity index 96% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.ui index 8454199a6b..fddd41ad6f 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.ui +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.ui @@ -1,167 +1,174 @@ QmitkUSCombinedModalityCreationWidget 0 0 323 350 0 350 Form 75 true Ultrasound Devices: 0 0 0 0 75 true Tracking Devices: 0 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Please select an ultrasound device and a tracking device from the lists above. These devices will be used to create a combined modality. Additionally, you may specifiy a vendor and a name.</span></p></body></html> true - - + + - Name + Vendor - - + + - Combined Modality + MBI - - + + - Vendor + Name - - + + - MBI + Combined Modality + + + + Activate Tracked Ultrasound + + + false Create Combined Modality :/USNavigation/accept.png:/USNavigation/accept.png Cancel :/USNavigation/restart.png:/USNavigation/restart.png QmitkServiceListWidget QWidget
QmitkServiceListWidget.h
1
SignalAborted()
diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.cpp similarity index 93% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.cpp index 7386a037de..87531c2631 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.cpp @@ -1,159 +1,159 @@ /*=================================================================== 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 "QmitkUSCombinedModalityEditWidget.h" #include "ui_QmitkUSCombinedModalityEditWidget.h" #include "mitkUSControlInterfaceBMode.h" #include "mitkUSControlInterfaceProbes.h" #include "../QmitkUSNavigationCalibrationsDataModel.h" #include "../QmitkUSNavigationCalibrationRemoveDelegate.h" #include "../QmitkUSNavigationCalibrationUpdateDepthDelegate.h" #include #include #include QmitkUSCombinedModalityEditWidget::QmitkUSCombinedModalityEditWidget(QWidget *parent) : QWidget(parent), m_CalibrationsDataModel(new QmitkUSNavigationCalibrationsDataModel(this)), m_CalibrationUpdateDepthDelegate(new QmitkUSNavigationCalibrationUpdateDepthDelegate(this)), ui(new Ui::QmitkUSCombinedModalityEditWidget) { ui->setupUi(this); ui->calibrationsTable->setModel(m_CalibrationsDataModel); ui->calibrationsTable->setItemDelegateForColumn(2, new QmitkUSNavigationCalibrationRemoveDelegate(this)); ui->calibrationsTable->setItemDelegateForColumn(0, m_CalibrationUpdateDepthDelegate); } QmitkUSCombinedModalityEditWidget::~QmitkUSCombinedModalityEditWidget() { delete ui; } -void QmitkUSCombinedModalityEditWidget::SetCombinedModality(mitk::USCombinedModality::Pointer combinedModality) +void QmitkUSCombinedModalityEditWidget::SetCombinedModality(mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality) { m_CalibrationsDataModel->SetCombinedModality(combinedModality); m_CombinedModality = combinedModality; if ( combinedModality.IsNull() ) { return; } m_LastCalibrations = m_CombinedModality->SerializeCalibration(); - ui->vendorLineEdit->setText(QString::fromStdString(combinedModality->GetManufacturer())); - ui->nameLineEdit->setText(QString::fromStdString(combinedModality->GetName())); + ui->vendorLineEdit->setText(QString::fromStdString(combinedModality->GetUltrasoundDevice()->GetManufacturer())); + ui->nameLineEdit->setText(QString::fromStdString(combinedModality->GetUltrasoundDevice()->GetName())); ui->ultrasoundDeviceLabel->setText(QString::fromStdString(combinedModality->GetUltrasoundDevice()->GetManufacturer() + " " + combinedModality->GetUltrasoundDevice()->GetName())); ui->trackingDeviceLabel->setText(QString::fromStdString(combinedModality->GetNavigationDataSource()->GetName())); mitk::USDevice::Pointer usDevice = combinedModality->GetUltrasoundDevice(); if ( usDevice.IsNull() ) { return; } mitk::USControlInterfaceBMode::Pointer controlInterfaceBMode = usDevice->GetControlInterfaceBMode(); if ( controlInterfaceBMode.IsNull() ) { return; } m_CalibrationUpdateDepthDelegate->SetControlInterfaceBMode(controlInterfaceBMode); } void QmitkUSCombinedModalityEditWidget::OnSaveButtonClicked() { if ( m_CombinedModality.IsNotNull() ) { - m_CombinedModality->SetManufacturer(ui->vendorLineEdit->text().toStdString()); - m_CombinedModality->SetName(ui->nameLineEdit->text().toStdString()); + m_CombinedModality->GetUltrasoundDevice()->SetManufacturer(ui->vendorLineEdit->text().toStdString()); + m_CombinedModality->GetUltrasoundDevice()->SetName(ui->nameLineEdit->text().toStdString()); m_LastCalibrations = m_CombinedModality->SerializeCalibration(); } emit SignalSaved(); } void QmitkUSCombinedModalityEditWidget::OnCancelButtonClicked() { if ( m_CombinedModality.IsNotNull() && ! m_LastCalibrations.empty() ) { // restore previous calibrations if cancel button was clicked m_CombinedModality->DeserializeCalibration(m_LastCalibrations); } emit SignalAborted(); } void QmitkUSCombinedModalityEditWidget::OnCalibrationsSaveButtonClicked() { if ( m_CombinedModality.IsNull() ) { MITK_WARN << "Cannot save calibrations as no combined modality is available."; return; } QString filename = QFileDialog::getSaveFileName( QApplication::activeWindow(), "Save Calibrations", "", "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); } void QmitkUSCombinedModalityEditWidget::OnCalibrationsLoadButtonClicked() { if ( m_CombinedModality.IsNull() ) { MITK_WARN << "Cannot load calibrations as no combined modality is available."; return; } QString filename = QFileDialog::getOpenFileName( QApplication::activeWindow(), "Load Calibration", "", "Calibration files *.cal" ); if ( filename.isNull() ) { return; } QFile file(filename); if ( ! file.open(QIODevice::ReadOnly | QIODevice::Text) ) { MITK_WARN << "Cannot open file '" << filename.toStdString() << "' for reading."; return; } QTextStream inStream(&file); std::string calibration = inStream.readAll().toStdString(); if ( calibration.empty() ) { MITK_WARN << "Failed to load file. Unsupported format?"; return; } try { m_CombinedModality->DeserializeCalibration(calibration, false); } catch ( const mitk::Exception& /*exception*/ ) { MITK_WARN << "Failed to deserialize calibration. Unsuppoerted format?"; return; } // make sure that the table model is up to date m_CalibrationsDataModel->SetCombinedModality(m_CombinedModality); } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.h similarity index 89% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.h index 0a97cf70b1..e1a822a14b 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.h +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.h @@ -1,61 +1,61 @@ /*=================================================================== 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 QMITKUSCOMBINEDMODALITYEDITWIDGET_H #define QMITKUSCOMBINEDMODALITYEDITWIDGET_H #include #include "mitkUSCombinedModality.h" namespace Ui { class QmitkUSCombinedModalityEditWidget; } class QmitkUSNavigationCalibrationsDataModel; class QmitkUSNavigationCalibrationUpdateDepthDelegate; class QmitkUSCombinedModalityEditWidget : public QWidget { Q_OBJECT signals: void SignalSaved(); void SignalAborted(); protected slots: void OnSaveButtonClicked(); void OnCancelButtonClicked(); void OnCalibrationsSaveButtonClicked(); void OnCalibrationsLoadButtonClicked(); public: explicit QmitkUSCombinedModalityEditWidget(QWidget *parent = 0); ~QmitkUSCombinedModalityEditWidget(); - void SetCombinedModality(mitk::USCombinedModality::Pointer combinedModality); + void SetCombinedModality(mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality); private: - mitk::USCombinedModality::Pointer m_CombinedModality; + mitk::AbstractUltrasoundTrackerDevice::Pointer m_CombinedModality; std::string m_LastCalibrations; QmitkUSNavigationCalibrationsDataModel* m_CalibrationsDataModel; QmitkUSNavigationCalibrationUpdateDepthDelegate* m_CalibrationUpdateDepthDelegate; Ui::QmitkUSCombinedModalityEditWidget* ui; }; #endif // QMITKUSCOMBINEDMODALITYEDITWIDGET_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.ui similarity index 97% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.ui index 85c8d9f55e..ad752a7e63 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.ui +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSCombinedModalityEditWidget.ui @@ -1,343 +1,352 @@ QmitkUSCombinedModalityEditWidget 0 0 404 - 418 + 456 0 350 Form <html><head/><body><p><span style=" font-weight:600;">Identifier:</span></p></body></html> Name Vendor Qt::Vertical QSizePolicy::Fixed 20 10 75 true Ultrasound Device: Qt::Vertical QSizePolicy::Fixed 20 10 75 true Tracking Device: Qt::Vertical QSizePolicy::Fixed 20 10 <html><head/><body><p><span style=" font-weight:600;">Calibrations:</span></p></body></html> QFrame::StyledPanel QFrame::Sunken + + + 0 + 50 + + + + Qt::ScrollBarAlwaysOn + QAbstractItemView::NoSelection 80 15 true false Load Calibrations from File System Load :/USNavigation/document-open.png:/USNavigation/document-open.png Write Calibrations to File System Write :/USNavigation/document-save.png:/USNavigation/document-save.png Qt::Vertical QSizePolicy::Fixed 20 20 true OK :/USNavigation/accept.png:/USNavigation/accept.png Cancel :/USNavigation/restart.png:/USNavigation/restart.png saveButton clicked() QmitkUSCombinedModalityEditWidget OnSaveButtonClicked() 104 347 201 184 cancelButton clicked() QmitkUSCombinedModalityEditWidget OnCancelButtonClicked() 299 347 201 184 calibrationsSaveButton clicked() QmitkUSCombinedModalityEditWidget OnCalibrationsSaveButtonClicked() 201 348 201 208 calibrationsLoadButton clicked() QmitkUSCombinedModalityEditWidget OnCalibrationsLoadButtonClicked() 109 337 201 208 SignalAborted() OnSaveButtonClicked() OnCancelButtonClicked() OnCalibrationsSaveButtonClicked() OnCalibrationsLoadButtonClicked() diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationFreezeButton.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSNavigationFreezeButton.cpp similarity index 96% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationFreezeButton.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSNavigationFreezeButton.cpp index 9017f35302..0d90347697 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationFreezeButton.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSNavigationFreezeButton.cpp @@ -1,136 +1,136 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkUSNavigationFreezeButton.h" #include QmitkUSNavigationFreezeButton::QmitkUSNavigationFreezeButton(QWidget* parent) : QPushButton(parent), m_OutputIndex(-1), m_FreezeButtonToggle(true) { this->setText("Freeze Imaging"); this->setIcon(QIcon(":/USNavigation/system-lock-screen.png")); this->setCheckable(true); //set shortcuts QShortcut *shortcut = new QShortcut(QKeySequence("F12"), parent); connect(shortcut, SIGNAL(activated()), this, SLOT(OnFreezeButtonToggle())); connect(this, SIGNAL(clicked(bool)), this, SLOT(OnButtonClicked(bool))); } QmitkUSNavigationFreezeButton::~QmitkUSNavigationFreezeButton() { } -void QmitkUSNavigationFreezeButton::SetCombinedModality(mitk::USCombinedModality::Pointer combinedModality, int outputIndex) +void QmitkUSNavigationFreezeButton::SetCombinedModality(mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality, int outputIndex) { m_CombinedModality = combinedModality; m_OutputIndex = outputIndex; } void QmitkUSNavigationFreezeButton::Freeze() { if ( ! this->isChecked() ) { this->setChecked(true); this->OnButtonClicked(true); } } void QmitkUSNavigationFreezeButton::Unfreeze() { if ( this->isChecked() ) { this->setChecked(false); this->OnButtonClicked(false); } } void QmitkUSNavigationFreezeButton::OnFreezeButtonToggle() { if(this->isVisible()) { this->setChecked(m_FreezeButtonToggle); OnButtonClicked(m_FreezeButtonToggle); } } void QmitkUSNavigationFreezeButton::OnButtonClicked(bool checked) { // cannot do anything without a combined modality if ( m_CombinedModality.IsNull() ) { MITK_WARN("QmitkUSNavigationFreezeButton") << "Cannot freeze the device as the device is null."; this->setChecked(false); m_FreezeButtonToggle = true; return; } m_FreezeButtonToggle = !checked; // cannot do anything without a navigation data source mitk::NavigationDataSource::Pointer navigationDataSource = m_CombinedModality->GetNavigationDataSource(); if ( navigationDataSource.IsNull() ) { MITK_WARN("QmitkUSNavigationFreezeButton") << "Cannot freeze the device as the NavigationDataSource is null."; this->setChecked(false); return; } if (checked) //freezing { MITK_INFO << "Freezing"; // freeze the imaging and the tracking m_CombinedModality->SetIsFreezed(true); if ( m_OutputIndex >= 0 ) { // make sure that the navigation data is up to date navigationDataSource->Update(); // unfreeze if the navigation data got invalid during the time between // the button click and the actual freeze if ( checked && ! navigationDataSource->GetOutput(m_OutputIndex)->IsDataValid() ) { MITK_WARN("QmitkUSNavigationStepZoneMarking")("QmitkUSNavigationStepTumourSelection") << "Unfreezing device as the last tracking data of the reference sensor wasn't valid."; m_CombinedModality->SetIsFreezed(false); this->setChecked(false); return; } } emit SignalFreezed(true); } else //unfreezing { MITK_INFO << "Unfreezing"; emit SignalFreezed(false); //m_CombinedModality->SetIsFreezed(false);//commented out to workaround bug: may only be unfreezed after critical structure was added } } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationFreezeButton.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSNavigationFreezeButton.h similarity index 92% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationFreezeButton.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSNavigationFreezeButton.h index f55d7a7c2a..6fe9e97ac0 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationFreezeButton.h +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSNavigationFreezeButton.h @@ -1,81 +1,81 @@ /*=================================================================== 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 QMITKUSNAVIGATIONFREEZEBUTTON_H #define QMITKUSNAVIGATIONFREEZEBUTTON_H #include #include "mitkUSCombinedModality.h" /** * \brief QPushButton for freezing and unfreezing a combined modality. * The button already has an icon and a text. On every successfull * freeze or unfreeze the signal SignalFrezzed() is emitted. One should * listen to this signal rather than to the clicked() signal of the * QPushButton as the combined modality may not be freezed after * clicked() was emitted. */ class QmitkUSNavigationFreezeButton : public QPushButton { Q_OBJECT signals: /** * \brief Emitted every time the freeze state of the combined modality changed. * True if the combined modality is freezed now, false if it isn't. */ void SignalFreezed(bool); protected slots: void OnButtonClicked(bool checked); void OnFreezeButtonToggle(); public: explicit QmitkUSNavigationFreezeButton(QWidget* parent = 0); ~QmitkUSNavigationFreezeButton(); /** * \brief Setter for the combined modality to be freezed by this button. * An index may be specified for a tracking data output. The combined * modality will only be freezed then, if the current tracking data of * this output is valid. */ - void SetCombinedModality(mitk::USCombinedModality::Pointer combinedModality, int outputIndex = -1); + void SetCombinedModality(mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality, int outputIndex = -1); /** * \brief Try to freeze the combined modality. * This does the same as clicking the button while the combined * modality isn't freezed. If the combined modality is already * freezed this method does nothing. */ void Freeze(); /** * \brief Unfreeze the combined modality. * This does the same as clicking the button while the combined * modality is freezed. If the combined modality isn't freezed * this method does nothing. */ void Unfreeze(); private: - mitk::USCombinedModality::Pointer m_CombinedModality; + mitk::AbstractUltrasoundTrackerDevice::Pointer m_CombinedModality; int m_OutputIndex; bool m_FreezeButtonToggle; }; #endif // QMITKUSNAVIGATIONFREEZEBUTTON_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationZoneDistancesWidget.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSNavigationZoneDistancesWidget.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationZoneDistancesWidget.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSNavigationZoneDistancesWidget.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationZoneDistancesWidget.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSNavigationZoneDistancesWidget.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationZoneDistancesWidget.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSNavigationZoneDistancesWidget.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSZoneManagementWidget.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSZoneManagementWidget.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSZoneManagementWidget.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSZoneManagementWidget.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSZoneManagementWidget.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSZoneManagementWidget.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSZoneManagementWidget.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSZoneManagementWidget.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSZoneManagementWidget.ui b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSZoneManagementWidget.ui similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSZoneManagementWidget.ui rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkUSZoneManagementWidget.ui diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkZoneProgressBar.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkZoneProgressBar.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkZoneProgressBar.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkZoneProgressBar.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkZoneProgressBar.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkZoneProgressBar.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkZoneProgressBar.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/Widgets/QmitkZoneProgressBar.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/mitkUSTargetPlacementQualityCalculator.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/mitkUSTargetPlacementQualityCalculator.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/mitkUSTargetPlacementQualityCalculator.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/mitkUSTargetPlacementQualityCalculator.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/mitkUSTargetPlacementQualityCalculator.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/mitkUSTargetPlacementQualityCalculator.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/mitkUSTargetPlacementQualityCalculator.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/mitkUSTargetPlacementQualityCalculator.h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/org_mbi_gui_qt_usnavigation_Activator.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/org_mbi_gui_qt_usnavigation_Activator.cpp similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/org_mbi_gui_qt_usnavigation_Activator.cpp rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/org_mbi_gui_qt_usnavigation_Activator.cpp diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/org_mbi_gui_qt_usnavigation_Activator.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/org_mbi_gui_qt_usnavigation_Activator.h similarity index 100% rename from Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/org_mbi_gui_qt_usnavigation_Activator.h rename to Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/org_mbi_gui_qt_usnavigation_Activator.h diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui index 8e043ac2f8..4c4ff80a50 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui @@ -1,954 +1,954 @@ QmitkMITKIGTTrackingToolboxViewControls 0 0 370 739 0 0 QmitkTemplate 0 Tracking QFrame::NoFrame QFrame::Raised 0 0 QFrame::NoFrame QFrame::Raised 10 75 true true Tracking Tools Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop 0 0 ToolStorage: <none> Qt::Horizontal 40 20 0 0 Qt::Horizontal 13 49 120 0 Auto Detection 120 0 Add Single Tool 120 0 Load Tool Storage 120 0 Reset QFrame::NoFrame QFrame::Raised 10 75 true Tracking Control Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Status: disconnected Qt::Horizontal 40 20 142 0 Connect Qt::Horizontal 40 20 142 0 Start Tracking Qt::Horizontal 40 20 <html><head/><body><p><span style=" color:#ff0000;">Tracking Frozen!</span></p></body></html> true 142 0 Freeze Tracking Qt::Vertical 20 40 Options Update Rate Options Update Rate [per second] Qt::Horizontal 40 20 100 - 30 + 10 Use different Render and Log Update Rates false Render Update Rate [fps] Qt::Horizontal 40 20 false 0 100 30 false Log Update Rate [per second] Qt::Horizontal 40 20 false 1 120 10 60 Other Options Show Tool Quaternions Simple UI Caution, only for backward compatibility: Inverse mode (Quaternions are stored inverse) Tracking Volume Options true Show Tracking Volume false Select Model: Tool Visualization Options true Show Tool Projection false Show Tool Axis Open IGT Link Enable Open IGT Link MicroService true Select Open IGT Link Data Format: TRANSFORM QTDATA TDATA POSITION Disable All Timers true <html><head/><body><p align="right"><span style=" color:#ff0000;">Rendering Disabled!</span></p></body></html> Qt::AutoText Qt::Vertical 20 40 Logging Filename: Choose File Limit Number Of Logged Frames: Qt::Horizontal 40 20 1 9999 300 CSV format true XML format Skip invalid data Logging Status Logging OFF Logged Frames: 0 Qt::Horizontal 40 20 Start Logging Stop Logging Qt::Vertical 20 40 9 742 303 70 70 50 Connect 70 50 Start Tracking Qt::Horizontal 40 20 70 50 Advanced Mode QmitkToolTrackingStatusWidget QWidget
QmitkToolTrackingStatusWidget.h
1
QmitkTrackingDeviceConfigurationWidget QWidget
QmitkTrackingDeviceConfigurationWidget.h
1
QmitkNavigationToolCreationWidget QWidget
QmitkNavigationToolCreationWidget.h
1
diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.cpp index dd91871bef..58a0bdbd51 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.cpp @@ -1,253 +1,254 @@ /*=================================================================== 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. ===================================================================*/ // Qmitk #include "QmitkMITKIGTTrackingToolboxViewWorker.h" #include QmitkMITKIGTTrackingToolboxViewWorker::QmitkMITKIGTTrackingToolboxViewWorker() { } QmitkMITKIGTTrackingToolboxViewWorker::~QmitkMITKIGTTrackingToolboxViewWorker() { } void QmitkMITKIGTTrackingToolboxViewWorker::SetWorkerMethod(WorkerMethod w) { m_WorkerMethod = w; } void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDevice(mitk::TrackingDevice::Pointer t) { m_TrackingDevice = t; } void QmitkMITKIGTTrackingToolboxViewWorker::SetDataStorage(mitk::DataStorage::Pointer d) { m_DataStorage = d; } void QmitkMITKIGTTrackingToolboxViewWorker::SetInverseMode(bool mode) { m_InverseMode = mode; } void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDeviceData(mitk::TrackingDeviceData d) { m_TrackingDeviceData = d; } void QmitkMITKIGTTrackingToolboxViewWorker::SetNavigationToolStorage(mitk::NavigationToolStorage::Pointer n) { m_NavigationToolStorage = n; } //! [Thread 7] void QmitkMITKIGTTrackingToolboxViewWorker::ThreadFunc() { switch (m_WorkerMethod) { case eAutoDetectTools: this->AutoDetectTools(); break; case eConnectDevice: this->ConnectDevice(); break; case eStartTracking: this->StartTracking(); break; case eStopTracking: this->StopTracking(); break; case eDisconnectDevice: this->DisconnectDevice(); break; default: MITK_WARN << "Undefined worker method was set ... something went wrong!"; break; } } //! [Thread 7] void QmitkMITKIGTTrackingToolboxViewWorker::AutoDetectTools() { mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New(m_DataStorage); try { mitk::NavigationToolStorage::Pointer tempStorage = m_TrackingDevice->AutoDetectTools(); for (unsigned int i = 0; i < tempStorage->GetToolCount(); i++) { autoDetectedStorage->AddTool(tempStorage->GetTool(i)); } } catch (mitk::Exception& e) { MITK_WARN << e.GetDescription(); emit AutoDetectToolsFinished(false, e.GetDescription()); return; } m_NavigationToolStorage = nullptr; m_NavigationToolStorage = autoDetectedStorage; emit AutoDetectToolsFinished(true, ""); MITK_INFO << "AutoDetect Tools Finished."; } void QmitkMITKIGTTrackingToolboxViewWorker::ConnectDevice() { std::string message = ""; //build the IGT pipeline mitk::TrackingDevice::Pointer trackingDevice = m_TrackingDevice; trackingDevice->SetData(m_TrackingDeviceData); //set device to rotation mode transposed becaus we are working with VNL style quaternions if (m_InverseMode) { trackingDevice->SetRotationMode(mitk::TrackingDevice::RotationTransposed); } //Get Tracking Volume Data mitk::TrackingDeviceData data = m_TrackingDeviceData; //Create Navigation Data Source with the factory class mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory = mitk::TrackingDeviceSourceConfigurator::New(m_NavigationToolStorage, trackingDevice); m_TrackingDeviceSource = myTrackingDeviceSourceFactory->CreateTrackingDeviceSource(m_ToolVisualizationFilter); if (m_TrackingDeviceSource.IsNull()) { message = std::string("Cannot connect to device: ") + myTrackingDeviceSourceFactory->GetErrorMessage(); emit ConnectDeviceFinished(false, QString(message.c_str())); return; } //set filter to rotation mode transposed becaus we are working with VNL style quaternions if (m_InverseMode) m_ToolVisualizationFilter->SetRotationMode(mitk::NavigationDataObjectVisualizationFilter::RotationTransposed); //First check if the created object is valid if (m_TrackingDeviceSource.IsNull()) { message = myTrackingDeviceSourceFactory->GetErrorMessage(); emit ConnectDeviceFinished(false, QString(message.c_str())); return; } MITK_INFO << "Connected device with " << m_TrackingDeviceSource->GetNumberOfOutputs() << " tools."; //connect to device try { m_TrackingDeviceSource->Connect(); //Microservice registration: + m_TrackingDeviceSource->SetToolMetaDataCollection(m_NavigationToolStorage); m_TrackingDeviceSource->RegisterAsMicroservice(); - m_NavigationToolStorage->SetSourceID(m_TrackingDeviceSource->GetMicroserviceID()); + m_NavigationToolStorage->SetSourceID(m_TrackingDeviceSource->GetMicroserviceID()); //DEPRECATED / not needed anymore because NavigationDataSource now holds a member of its tool storage. Only left for backward compatibility. m_NavigationToolStorage->LockStorage(); } catch (...) //todo: change to mitk::IGTException { message = "Error on connecting the tracking device."; emit ConnectDeviceFinished(false, QString(message.c_str())); return; } emit ConnectDeviceFinished(true, QString(message.c_str())); } mitk::TrackingDeviceSource::Pointer QmitkMITKIGTTrackingToolboxViewWorker::GetTrackingDeviceSource() { return this->m_TrackingDeviceSource; } void QmitkMITKIGTTrackingToolboxViewWorker::StartTracking() { QString errorMessage = ""; try { m_TrackingDeviceSource->StartTracking(); } catch (...) //todo: change to mitk::IGTException { errorMessage += "Error while starting the tracking device!"; emit StartTrackingFinished(false, errorMessage); return; } //remember the original colors of the tools m_OriginalColors = std::map(); for (unsigned int i = 0; i < this->m_NavigationToolStorage->GetToolCount(); i++) { mitk::DataNode::Pointer currentToolNode = m_NavigationToolStorage->GetTool(i)->GetDataNode(); float c[3]; currentToolNode->GetColor(c); mitk::Color color; color.SetRed(c[0]); color.SetGreen(c[1]); color.SetBlue(c[2]); m_OriginalColors[currentToolNode] = color; } emit StartTrackingFinished(true, errorMessage); } void QmitkMITKIGTTrackingToolboxViewWorker::StopTracking() { //stop tracking try { m_TrackingDeviceSource->StopTracking(); } catch (mitk::Exception& e) { emit StopTrackingFinished(false, e.GetDescription()); } //restore the original colors of the tools for (unsigned int i = 0; i < this->m_NavigationToolStorage->GetToolCount(); i++) { mitk::DataNode::Pointer currentToolNode = m_NavigationToolStorage->GetTool(i)->GetDataNode(); if (m_OriginalColors.find(currentToolNode) == m_OriginalColors.end()) { MITK_WARN << "Cannot restore original color of tool " << m_NavigationToolStorage->GetTool(i)->GetToolName(); } else { currentToolNode->SetColor(m_OriginalColors[currentToolNode]); } } // clear map m_OriginalColors m_OriginalColors.clear(); //emit signal emit StopTrackingFinished(true, ""); } void QmitkMITKIGTTrackingToolboxViewWorker::DisconnectDevice() { try { if (m_TrackingDeviceSource->IsTracking()) { m_TrackingDeviceSource->StopTracking(); } m_TrackingDeviceSource->Disconnect(); m_TrackingDeviceSource->UnRegisterMicroservice(); m_NavigationToolStorage->UnLockStorage(); m_TrackingDeviceSource = nullptr; } catch (mitk::Exception& e) { emit DisconnectDeviceFinished(false, e.GetDescription()); } emit DisconnectDeviceFinished(true, ""); } diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp index 6cc68441e8..e50832db81 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp @@ -1,239 +1,240 @@ /*=================================================================== 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. ===================================================================*/ // Qmitk #include "QmitkNavigationDataPlayerView.h" // QT #include #include //mitk #include #include #include #include #include #include // VTK #include const std::string QmitkNavigationDataPlayerView::VIEW_ID = "org.mitk.views.navigationdataplayer"; QmitkNavigationDataPlayerView::QmitkNavigationDataPlayerView() : m_Controls( 0 ) { } QmitkNavigationDataPlayerView::~QmitkNavigationDataPlayerView() { } void QmitkNavigationDataPlayerView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkNavigationDataPlayerViewControls; m_Controls->setupUi( parent ); this->CreateConnections(); // make deselected Player invisible m_Controls->m_TimedWidget->setVisible(false); } } void QmitkNavigationDataPlayerView::SetFocus() { if ( m_Controls ) { m_Controls->m_grpbxControls->setFocus(); } } void QmitkNavigationDataPlayerView::CreateConnections() { connect( m_Controls->m_RdbSequential, SIGNAL(released()), this, SLOT(OnSelectPlayer()) ); connect( m_Controls->m_RdbTimeBased, SIGNAL(released()), this, SLOT(OnSelectPlayer()) ); connect( m_Controls->m_BtnOpenFile, SIGNAL(released()), this, SLOT(OnOpenFile()) ); connect( m_Controls->m_ChkDisplay, SIGNAL(released()), this, SLOT(OnSetDisplay()) ); connect( m_Controls->m_chkRepeat, SIGNAL(stateChanged(int)), this, SLOT(OnSetRepeat(int)) ); connect( m_Controls->m_ChkMicroservice, SIGNAL(released()), this, SLOT(OnSetMicroservice()) ); connect( m_Controls->m_SequentialWidget, SIGNAL(SignalUpdate()), this, SLOT(OnUpdate()) ); connect( m_Controls->m_TimedWidget, SIGNAL(SignalUpdate()), this, SLOT(OnUpdate()) ); this->SetInteractionComponentsEnabledState(false); } void QmitkNavigationDataPlayerView::OnOpenFile() { mitk::NavigationDataReaderInterface::Pointer reader = nullptr; QString filter = tr("NavigationData File (*.csv *.xml)"); QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open NavigationData Set"), "", filter); if ( fileName.isNull() ) { return; } // user pressed cancel try { m_Data = dynamic_cast (mitk::IOUtil::Load(fileName.toStdString())[0].GetPointer()); } catch ( const mitk::Exception &e ) { MITK_WARN("NavigationDataPlayerView") << "could not open file " << fileName.toStdString(); QMessageBox::critical(0, "Error Reading File", "The file '" + fileName +"' could not be read.\n" + e.GetDescription() ); return; } if (m_Controls->m_ChkConvertToPointSet->isChecked()) m_Data->ConvertNavigationDataToPointSet(); // Update Labels m_Controls->m_LblFilePath->setText(fileName); m_Controls->m_LblFrames->setText(QString::number(m_Data->Size())); m_Controls->m_LblTools->setText(QString::number(m_Data->GetNumberOfTools())); // Initialize Widgets and create Player this->OnSelectPlayer(); this->SetInteractionComponentsEnabledState(true); } void QmitkNavigationDataPlayerView::OnSelectPlayer() { if (m_Controls->m_RdbSequential->isChecked()) { m_Controls->m_SequentialWidget->setVisible(true); m_Controls->m_TimedWidget->setVisible(false); mitk::NavigationDataSequentialPlayer::Pointer seqPlayer = mitk::NavigationDataSequentialPlayer::New(); seqPlayer->SetNavigationDataSet(m_Data); m_Controls->m_SequentialWidget->SetPlayer(seqPlayer); m_Player = seqPlayer; } else { m_Controls->m_SequentialWidget->setVisible(false); m_Controls->m_TimedWidget->setVisible(true); mitk::NavigationDataPlayer::Pointer timedPlayer = mitk::NavigationDataPlayer::New(); timedPlayer->SetNavigationDataSet(m_Data); m_Controls->m_TimedWidget->SetPlayer(timedPlayer); m_Player = timedPlayer; } this->ConfigurePlayer(); // SetupRenderingPipeline this->OnSetDisplay(); } void QmitkNavigationDataPlayerView::ConfigurePlayer() { // set repeat mode according to the checkbox m_Player->SetRepeat( m_Controls->m_chkRepeat->isChecked() ); } void QmitkNavigationDataPlayerView::OnSetRepeat(int checkState) { m_Player->SetRepeat(checkState != 0); } void QmitkNavigationDataPlayerView::OnSetMicroservice(){ if(m_Controls->m_ChkMicroservice->isChecked()) { m_ToolStorage = mitk::NavigationToolStorage::New(); for (itk::ProcessObject::DataObjectPointerArraySizeType i = 0; i < m_Player->GetNumberOfIndexedOutputs(); i++) { mitk::NavigationTool::Pointer currentDummyTool = mitk::NavigationTool::New(); mitk::VirtualTrackingTool::Pointer dummyTool = mitk::VirtualTrackingTool::New(); std::stringstream name; name << "Virtual Tool " << i; dummyTool->SetToolName(name.str()); currentDummyTool->SetDataNode(m_RenderingNodes.at(i)); currentDummyTool->SetIdentifier(name.str()); m_ToolStorage->AddTool(currentDummyTool); } - m_Player->RegisterAsMicroservice(); m_ToolStorage->SetName("NavigationDataPlayer Tool Storage"); - m_ToolStorage->SetSourceID(m_Player->GetMicroserviceID()); + m_Player->SetToolMetaDataCollection(m_ToolStorage); + m_Player->RegisterAsMicroservice(); + m_ToolStorage->SetSourceID(m_Player->GetMicroserviceID()); //DEPRECATED / not needed anymore because NavigationDataSource now holds a member of its tool storage. Only left for backward compatibility. m_ToolStorage->RegisterAsMicroservice(); } else { if (m_ToolStorage.IsNotNull()) m_ToolStorage->UnRegisterMicroservice(); m_ToolStorage = nullptr; m_Player->UnRegisterMicroservice(); } } void QmitkNavigationDataPlayerView::OnUpdate(){ if (m_VisFilter.IsNotNull()) { m_VisFilter->Update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkNavigationDataPlayerView::OnSetDisplay(){ DestroyPipeline(); if ( (m_Controls->m_ChkDisplay->isChecked()) && ( m_Player.IsNotNull() )) { CreatePipeline(); } } void QmitkNavigationDataPlayerView::CreatePipeline(){ m_VisFilter = mitk::NavigationDataObjectVisualizationFilter::New(); m_VisFilter->ConnectTo(m_Player); for (unsigned int i = 0 ; i < m_Player->GetNumberOfIndexedOutputs(); i++ ) { mitk::DataNode::Pointer node = mitk::DataNode::New(); QString name = "Recorded Tool " + QString::number(i + 1); node->SetName(name.toStdString()); //create small sphere and use it as surface mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkSmartPointer vtkData = vtkSmartPointer::New(); vtkData->SetRadius(5.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); node->SetData(mySphere); m_VisFilter->SetRepresentationObject(i, mySphere); // Add Node to DataStorageand to local list of Nodes GetDataStorage()->Add(node); m_RenderingNodes.push_back(node); } m_VisFilter->Update(); mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(GetDataStorage()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkNavigationDataPlayerView::DestroyPipeline(){ m_VisFilter = nullptr; for (unsigned int i = 0; i < m_RenderingNodes.size(); i++){ this->GetDataStorage()->Remove(m_RenderingNodes[i]); } m_RenderingNodes.clear(); } void QmitkNavigationDataPlayerView::SetInteractionComponentsEnabledState(bool isActive){ m_Controls->m_grpbxSettings->setEnabled(isActive); m_Controls->m_grpbxControls->setEnabled(isActive); } diff --git a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/QmitkUltrasoundSupport.cpp b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/QmitkUltrasoundSupport.cpp index 51f6110989..4595f43540 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/QmitkUltrasoundSupport.cpp +++ b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/QmitkUltrasoundSupport.cpp @@ -1,533 +1,587 @@ /*=================================================================== 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 //Mitk #include #include #include #include #include // Qmitk #include "QmitkUltrasoundSupport.h" // Qt #include #include #include // Ultrasound #include "mitkUSDevice.h" #include "QmitkUSAbstractCustomWidget.h" #include #include #include "usServiceReference.h" #include "internal/org_mitk_gui_qt_ultrasound_Activator.h" const std::string QmitkUltrasoundSupport::VIEW_ID = "org.mitk.views.ultrasoundsupport"; QmitkUltrasoundSupport::QmitkUltrasoundSupport() : m_Controls(nullptr), m_ControlCustomWidget(0), m_ControlBModeWidget(0), m_ControlProbesWidget(0), m_ImageAlreadySetToNode(false), m_CurrentImageWidth(0), m_CurrentImageHeight(0) { ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); if (pluginContext) { // to be notified about service event of an USDevice pluginContext->connectServiceListener(this, "OnDeviceServiceEvent", QString::fromStdString("(" + us::ServiceConstants::OBJECTCLASS() + "=" + us_service_interface_iid() + ")")); } } QmitkUltrasoundSupport::~QmitkUltrasoundSupport() { try { StoreUISettings(); StopTimers(); // Get all active devicesand deactivate them to prevent freeze std::vector devices = this->m_Controls->m_ActiveVideoDevices->GetAllServices(); for (size_t i = 0; i < devices.size(); i++) { mitk::USDevice::Pointer device = devices[i]; if (device.IsNotNull() && device->GetIsActive()) { device->Deactivate(); device->Disconnect(); } } } catch (std::exception &e) { MITK_ERROR << "Exception during call of destructor! Message: " << e.what(); } } void QmitkUltrasoundSupport::SetFocus() { } void QmitkUltrasoundSupport::CreateQtPartControl(QWidget *parent) { //initialize timers m_UpdateTimer = new QTimer(this); m_RenderingTimer2d = new QTimer(this); m_RenderingTimer3d = new QTimer(this); // build up qt view, unless already done if (!m_Controls) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::UltrasoundSupportControls; // create GUI widgets from the Qt Designer's .ui file m_Controls->setupUi(parent); //load persistence data before connecting slots (so no slots are called in this phase...) LoadUISettings(); //connect signals and slots... connect(m_Controls->m_DeviceManagerWidget, SIGNAL(NewDeviceButtonClicked()), this, SLOT(OnClickedAddNewDevice())); // Change Widget Visibilities connect(m_Controls->m_DeviceManagerWidget, SIGNAL(NewDeviceButtonClicked()), this->m_Controls->m_NewVideoDeviceWidget, SLOT(CreateNewDevice())); // Init NewDeviceWidget connect(m_Controls->m_ActiveVideoDevices, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(OnChangedActiveDevice())); connect(m_Controls->m_RunImageTimer, SIGNAL(clicked()), this, SLOT(OnChangedActiveDevice())); connect(m_Controls->m_ShowImageStream, SIGNAL(clicked()), this, SLOT(OnChangedActiveDevice())); connect(m_Controls->m_NewVideoDeviceWidget, SIGNAL(Finished()), this, SLOT(OnNewDeviceWidgetDone())); // After NewDeviceWidget finished editing connect(m_Controls->m_FrameRatePipeline, SIGNAL(valueChanged(int)), this, SLOT(OnChangedFramerateLimit())); connect(m_Controls->m_FrameRate2d, SIGNAL(valueChanged(int)), this, SLOT(OnChangedFramerateLimit())); connect(m_Controls->m_FrameRate3d, SIGNAL(valueChanged(int)), this, SLOT(OnChangedFramerateLimit())); connect(m_Controls->m_FreezeButton, SIGNAL(clicked()), this, SLOT(OnClickedFreezeButton())); connect(m_UpdateTimer, SIGNAL(timeout()), this, SLOT(UpdateImage())); connect(m_RenderingTimer2d, SIGNAL(timeout()), this, SLOT(RenderImage2d())); connect(m_RenderingTimer3d, SIGNAL(timeout()), this, SLOT(RenderImage3d())); connect(m_Controls->m_Update2DView, SIGNAL(clicked()), this, SLOT(StartTimers())); connect(m_Controls->m_Update3DView, SIGNAL(clicked()), this, SLOT(StartTimers())); connect(m_Controls->m_DeviceManagerWidget, SIGNAL(EditDeviceButtonClicked(mitk::USDevice::Pointer)), this, SLOT(OnClickedEditDevice())); //Change Widget Visibilities connect(m_Controls->m_DeviceManagerWidget, SIGNAL(EditDeviceButtonClicked(mitk::USDevice::Pointer)), this->m_Controls->m_NewVideoDeviceWidget, SLOT(EditDevice(mitk::USDevice::Pointer))); + connect(m_Controls->m_SetXPoint1, SIGNAL(clicked()), this, SLOT(SetXPoint1())); + connect(m_Controls->m_SetXPoint2, SIGNAL(clicked()), this, SLOT(SetXPoint2())); + connect(m_Controls->m_SetYPoint1, SIGNAL(clicked()), this, SLOT(SetYPoint1())); + connect(m_Controls->m_SetYPoint2, SIGNAL(clicked()), this, SLOT(SetYPoint2())); + connect(m_Controls->m_SaveSpacing, SIGNAL(clicked()), this, SLOT(WriteSpacingToDevice())); + + // Initializations m_Controls->m_NewVideoDeviceWidget->setVisible(false); std::string filter = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice)(" + mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISACTIVE + "=true))"; m_Controls->m_ActiveVideoDevices->Initialize( mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL, filter); m_Controls->m_ActiveVideoDevices->SetAutomaticallySelectFirstEntry(true); m_FrameCounterPipeline = 0; m_FrameCounter2d = 0; m_FrameCounter3d = 0; m_Controls->tabWidget->setTabEnabled(1, false); } } void QmitkUltrasoundSupport::OnClickedAddNewDevice() { m_Controls->m_NewVideoDeviceWidget->setVisible(true); m_Controls->m_DeviceManagerWidget->setVisible(false); m_Controls->m_Headline->setText("Add New Video Device:"); m_Controls->m_WidgetActiveDevices->setVisible(false); } void QmitkUltrasoundSupport::OnClickedEditDevice() { m_Controls->m_NewVideoDeviceWidget->setVisible(true); m_Controls->m_DeviceManagerWidget->setVisible(false); m_Controls->m_WidgetActiveDevices->setVisible(false); m_Controls->m_Headline->setText("Edit Video Device:"); } void QmitkUltrasoundSupport::UpdateImage() { //Update device m_Device->Modified(); m_Device->Update(); //Only update the view if the image is shown if (m_Controls->m_ShowImageStream->isChecked()) { //Update data nodes for (size_t i = 0; i < m_AmountOfOutputs; i++) { mitk::Image::Pointer curOutput = m_Device->GetOutput(i); if (curOutput->IsEmpty()) { m_Node.at(i)->SetName("No Data received yet ..."); //create a noise image for correct initialization of level window, etc. mitk::Image::Pointer randomImage = mitk::ImageGenerator::GenerateRandomImage(32, 32, 1, 1, 1, 1, 1, 255, 0); m_Node.at(i)->SetData(randomImage); curOutput->SetGeometry(randomImage->GetGeometry()); } else { std::stringstream nodeName; nodeName << "US Viewing Stream - Image " << i; m_Node.at(i)->SetName(nodeName.str()); m_Node.at(i)->SetData(curOutput); m_Node.at(i)->Modified(); } // if the geometry changed: reinitialize the ultrasound image if ((i==0) && (m_OldGeometry.IsNotNull()) && (curOutput->GetGeometry() != NULL) && (!mitk::Equal(*(m_OldGeometry.GetPointer()), *(curOutput->GetGeometry()), 0.0001, false)) ) { mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart(); if ((renderWindow != NULL) && (curOutput->GetTimeGeometry()->IsValid()) && (m_Controls->m_ShowImageStream->isChecked())) { renderWindow->GetRenderingManager()->InitializeViews( curOutput->GetGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); renderWindow->GetRenderingManager()->RequestUpdateAll(); } m_CurrentImageWidth = curOutput->GetDimension(0); m_CurrentImageHeight = curOutput->GetDimension(1); m_OldGeometry = dynamic_cast(curOutput->GetGeometry()); } } } //Update frame counter m_FrameCounterPipeline++; if (m_FrameCounterPipeline >0) { //compute framerate of pipeline update int nMilliseconds = m_Clock.restart(); int fps = 1000.0 / nMilliseconds; m_FPSPipeline = fps; m_FrameCounterPipeline = 0; //display lowest framerate in UI int lowestFPS = m_FPSPipeline; if (m_Controls->m_Update2DView->isChecked() && (m_FPS2d < lowestFPS)) { lowestFPS = m_FPS2d; } if (m_Controls->m_Update3DView->isChecked() && (m_FPS3d < lowestFPS)) { lowestFPS = m_FPS3d; } m_Controls->m_FramerateLabel->setText("Current Framerate: " + QString::number(lowestFPS) + " FPS"); } } void QmitkUltrasoundSupport::RenderImage2d() { if (!m_Controls->m_Update2DView->isChecked()) return; this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); m_FrameCounter2d++; if (m_FrameCounter2d >0) { //compute framerate of 2d render window update int nMilliseconds = m_Clock2d.restart(); int fps = 1000.0f / (nMilliseconds); m_FPS2d = fps; m_FrameCounter2d = 0; } } void QmitkUltrasoundSupport::RenderImage3d() { if (!m_Controls->m_Update3DView->isChecked()) return; this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS); m_FrameCounter3d++; if (m_FrameCounter3d >0) { //compute framerate of 2d render window update int nMilliseconds = m_Clock3d.restart(); int fps = 1000.0f / (nMilliseconds); m_FPS3d = fps; m_FrameCounter3d = 0; } } void QmitkUltrasoundSupport::OnChangedFramerateLimit() { StopTimers(); int intervalPipeline = (1000 / m_Controls->m_FrameRatePipeline->value()); int interval2D = (1000 / m_Controls->m_FrameRate2d->value()); int interval3D = (1000 / m_Controls->m_FrameRate3d->value()); SetTimerIntervals(intervalPipeline, interval2D, interval3D); StartTimers(); } void QmitkUltrasoundSupport::OnClickedFreezeButton() { if (m_Device.IsNull()) { MITK_WARN("UltrasoundSupport") << "Freeze button clicked though no device is selected."; return; } if (m_Device->GetIsFreezed()) { m_Device->SetIsFreezed(false); m_Controls->m_FreezeButton->setText("Freeze"); } else { m_Device->SetIsFreezed(true); m_Controls->m_FreezeButton->setText("Start Viewing Again"); } } void QmitkUltrasoundSupport::OnChangedActiveDevice() { - if (m_Controls->m_RunImageTimer->isChecked() == false) - { - StopTimers(); - return; - } - //clean up and stop timer StopTimers(); this->RemoveControlWidgets(); for (size_t j = 0; j < m_Node.size(); j++) { this->GetDataStorage()->Remove(m_Node.at(j)); m_Node.at(j)->ReleaseData(); } m_Node.clear(); //get current device, abort if it is invalid m_Device = m_Controls->m_ActiveVideoDevices->GetSelectedService(); if (m_Device.IsNull()) { m_Controls->tabWidget->setTabEnabled(1, false); return; } m_AmountOfOutputs = m_Device->GetNumberOfIndexedOutputs(); // clear data storage, create new nodes and add for (size_t i = 0; i < m_AmountOfOutputs; i++) { mitk::DataNode::Pointer currentNode = mitk::DataNode::New(); std::stringstream nodeName; nodeName << "US Viewing Stream - Image " << i; currentNode->SetName(nodeName.str()); //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); currentNode->SetData(dummyImage); m_OldGeometry = dynamic_cast(dummyImage->GetGeometry()); m_Node.push_back(currentNode); //show node if the option is enabled if (m_Controls->m_ShowImageStream->isChecked()) { this->GetDataStorage()->Add(m_Node.at(i)); } } //create the widgets for this device and enable the widget tab this->CreateControlWidgets(); m_Controls->tabWidget->setTabEnabled(1, true); //start timer if (m_Controls->m_RunImageTimer->isChecked()) { int intervalPipeline = (1000 / m_Controls->m_FrameRatePipeline->value()); int interval2D = (1000 / m_Controls->m_FrameRate2d->value()); int interval3D = (1000 / m_Controls->m_FrameRate3d->value()); SetTimerIntervals(intervalPipeline, interval2D, interval3D); StartTimers(); m_Controls->m_TimerWidget->setEnabled(true); } else { m_Controls->m_TimerWidget->setEnabled(false); } } void QmitkUltrasoundSupport::OnNewDeviceWidgetDone() { m_Controls->m_NewVideoDeviceWidget->setVisible(false); m_Controls->m_DeviceManagerWidget->setVisible(true); m_Controls->m_Headline->setText("Ultrasound Devices:"); m_Controls->m_WidgetActiveDevices->setVisible(true); } void QmitkUltrasoundSupport::CreateControlWidgets() { m_ControlProbesWidget = new QmitkUSControlsProbesWidget(m_Device->GetControlInterfaceProbes(), m_Controls->m_ToolBoxControlWidgets); m_Controls->probesWidgetContainer->addWidget(m_ControlProbesWidget); // create b mode widget for current device m_ControlBModeWidget = new QmitkUSControlsBModeWidget(m_Device->GetControlInterfaceBMode(), m_Controls->m_ToolBoxControlWidgets); m_Controls->m_ToolBoxControlWidgets->addItem(m_ControlBModeWidget, "B Mode Controls"); if (!m_Device->GetControlInterfaceBMode()) { m_Controls->m_ToolBoxControlWidgets->setItemEnabled(m_Controls->m_ToolBoxControlWidgets->count() - 1, false); } // create doppler widget for current device m_ControlDopplerWidget = new QmitkUSControlsDopplerWidget(m_Device->GetControlInterfaceDoppler(), m_Controls->m_ToolBoxControlWidgets); m_Controls->m_ToolBoxControlWidgets->addItem(m_ControlDopplerWidget, "Doppler Controls"); if (!m_Device->GetControlInterfaceDoppler()) { m_Controls->m_ToolBoxControlWidgets->setItemEnabled(m_Controls->m_ToolBoxControlWidgets->count() - 1, false); } ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); if (pluginContext) { std::string filter = "(org.mitk.services.UltrasoundCustomWidget.deviceClass=" + m_Device->GetDeviceClass() + ")"; + //Hint: The following three lines are a workaround. Till now the only US video device was an USVideoDevice. + // And everything worked fine. However, the ultrasound image source can be an USIGTLDevice (IGTL Client), as well. + // This second option wasn't considered yet. So, the custom control widget will work correctly only, if + // the filter declares the device class as org.mitk.modules.us.USVideoDevice. Another option, how to deal with + // the two possible ultrasound image devices would be to change the returned string of the method + // std::string QmitkUSControlsCustomVideoDeviceWidget::GetDeviceClass(), which always returns the string + // org.mitk.modules.us.USVideoDevice of the USVideoDevice class. If there is a possility to change the + // returned string dynamically between "IGTL Client" and "org.mitk.modules.us.USVideoDevice" the following + // three lines will not be needed. + if (m_Device->GetDeviceClass().compare("IGTL Client") == 0) + { + filter = "(org.mitk.services.UltrasoundCustomWidget.deviceClass=" + mitk::USVideoDevice::GetDeviceClassStatic() + ")"; + } QString interfaceName = QString::fromStdString(us_service_interface_iid()); m_CustomWidgetServiceReference = pluginContext->getServiceReferences(interfaceName, QString::fromStdString(filter)); if (m_CustomWidgetServiceReference.size() > 0) { m_ControlCustomWidget = pluginContext->getService (m_CustomWidgetServiceReference.at(0))->CloneForQt(m_Controls->tab2); m_ControlCustomWidget->SetDevice(m_Device); m_Controls->m_ToolBoxControlWidgets->addItem(m_ControlCustomWidget, "Custom Controls"); } else { m_Controls->m_ToolBoxControlWidgets->addItem(new QWidget(m_Controls->m_ToolBoxControlWidgets), "Custom Controls"); m_Controls->m_ToolBoxControlWidgets->setItemEnabled(m_Controls->m_ToolBoxControlWidgets->count() - 1, false); } } // select first enabled control widget for (int n = 0; n < m_Controls->m_ToolBoxControlWidgets->count(); ++n) { if (m_Controls->m_ToolBoxControlWidgets->isItemEnabled(n)) { m_Controls->m_ToolBoxControlWidgets->setCurrentIndex(n); break; } } } void QmitkUltrasoundSupport::RemoveControlWidgets() { if (!m_ControlProbesWidget) { return; } //widgets do not exist... nothing to do // remove all control widgets from the tool box widget while (m_Controls->m_ToolBoxControlWidgets->count() > 0) { m_Controls->m_ToolBoxControlWidgets->removeItem(0); } // remove probes widget (which is not part of the tool box widget) m_Controls->probesWidgetContainer->removeWidget(m_ControlProbesWidget); delete m_ControlProbesWidget; m_ControlProbesWidget = 0; delete m_ControlBModeWidget; m_ControlBModeWidget = 0; delete m_ControlDopplerWidget; m_ControlDopplerWidget = 0; // delete custom widget if it is present if (m_ControlCustomWidget) { ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); delete m_ControlCustomWidget; m_ControlCustomWidget = 0; if (m_CustomWidgetServiceReference.size() > 0) { pluginContext->ungetService(m_CustomWidgetServiceReference.at(0)); } } } void QmitkUltrasoundSupport::OnDeviceServiceEvent(const ctkServiceEvent event) { if (m_Device.IsNull() || event.getType() != ctkServiceEvent::MODIFIED) { return; } ctkServiceReference service = event.getServiceReference(); if (m_Device->GetManufacturer() != service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_MANUFACTURER)).toString().toStdString() && m_Device->GetName() != service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_NAME)).toString().toStdString()) { return; } if (!m_Device->GetIsActive() && m_UpdateTimer->isActive()) { StopTimers(); } if (m_CurrentDynamicRange != service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DYNAMIC_RANGE)).toDouble()) { m_CurrentDynamicRange = service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DYNAMIC_RANGE)).toDouble(); // update level window for the current dynamic range mitk::LevelWindow levelWindow; m_Node.at(0)->GetLevelWindow(levelWindow); levelWindow.SetAuto(m_curOutput.at(0), true, true); m_Node.at(0)->SetLevelWindow(levelWindow); } } void QmitkUltrasoundSupport::StoreUISettings() { QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); settings.setValue("DisplayImage", QVariant(m_Controls->m_ShowImageStream->isChecked())); settings.setValue("RunImageTimer", QVariant(m_Controls->m_RunImageTimer->isChecked())); settings.setValue("Update2DView", QVariant(m_Controls->m_Update2DView->isChecked())); settings.setValue("Update3DView", QVariant(m_Controls->m_Update3DView->isChecked())); settings.setValue("UpdateRatePipeline", QVariant(m_Controls->m_FrameRatePipeline->value())); settings.setValue("UpdateRate2d", QVariant(m_Controls->m_FrameRate2d->value())); settings.setValue("UpdateRate3d", QVariant(m_Controls->m_FrameRate3d->value())); settings.endGroup(); } void QmitkUltrasoundSupport::LoadUISettings() { QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); m_Controls->m_ShowImageStream->setChecked(settings.value("DisplayImage", true).toBool()); m_Controls->m_RunImageTimer->setChecked(settings.value("RunImageTimer", true).toBool()); m_Controls->m_Update2DView->setChecked(settings.value("Update2DView", true).toBool()); m_Controls->m_Update3DView->setChecked(settings.value("Update3DView", true).toBool()); m_Controls->m_FrameRatePipeline->setValue(settings.value("UpdateRatePipeline", 50).toInt()); m_Controls->m_FrameRate2d->setValue(settings.value("UpdateRate2d", 20).toInt()); m_Controls->m_FrameRate3d->setValue(settings.value("UpdateRate3d", 5).toInt()); settings.endGroup(); } void QmitkUltrasoundSupport::StartTimers() { m_Clock.start(); m_UpdateTimer->start(); if (m_Controls->m_Update2DView->isChecked()) { m_RenderingTimer2d->start(); } if (m_Controls->m_Update3DView->isChecked()) { m_RenderingTimer3d->start(); } } void QmitkUltrasoundSupport::StopTimers() { m_UpdateTimer->stop(); m_RenderingTimer2d->stop(); m_RenderingTimer3d->stop(); } void QmitkUltrasoundSupport::SetTimerIntervals(int intervalPipeline, int interval2D, int interval3D) { m_UpdateTimer->setInterval(intervalPipeline); m_RenderingTimer2d->setInterval(interval2D); m_RenderingTimer3d->setInterval(interval3D); } + + +/* Spacing methods */ +void QmitkUltrasoundSupport::SetXPoint1() +{ + m_Xpoint1 = this->GetRenderWindowPart()->GetSelectedPosition(); + m_XSpacing = ComputeSpacing(m_Xpoint1, m_Xpoint2, m_Controls->m_XDistance->value()); + m_Controls->m_XSpacing->setText(QString("X Spacing: ") + QString::number(m_XSpacing) + " mm"); +} +void QmitkUltrasoundSupport::SetXPoint2() +{ + m_Xpoint2 = this->GetRenderWindowPart()->GetSelectedPosition(); + m_XSpacing = ComputeSpacing(m_Xpoint1, m_Xpoint2, m_Controls->m_XDistance->value()); + m_Controls->m_XSpacing->setText(QString("X Spacing: ") + QString::number(m_XSpacing) + " mm"); +} +void QmitkUltrasoundSupport::SetYPoint1() +{ + m_Ypoint1 = this->GetRenderWindowPart()->GetSelectedPosition(); + m_YSpacing = ComputeSpacing(m_Ypoint1, m_Ypoint2, m_Controls->m_YDistance->value()); + m_Controls->m_YSpacing->setText(QString("Y Spacing: ") + QString::number(m_YSpacing) + " mm"); +} +void QmitkUltrasoundSupport::SetYPoint2() +{ + m_Ypoint2 = this->GetRenderWindowPart()->GetSelectedPosition(); + m_YSpacing = ComputeSpacing(m_Ypoint1, m_Ypoint2, m_Controls->m_YDistance->value()); + m_Controls->m_YSpacing->setText(QString("Y Spacing: ") + QString::number(m_YSpacing) + " mm"); +} +void QmitkUltrasoundSupport::WriteSpacingToDevice() +{ + this->m_Device->SetSpacing(m_XSpacing, m_YSpacing); + MITK_INFO << "Spacing saved to device object, please save device data to permanently store the spacing."; +} +double QmitkUltrasoundSupport::ComputeSpacing(mitk::Point3D p1, mitk::Point3D p2, double distance) +{ + double spacing = 0; + double pointDistance = p1.EuclideanDistanceTo(p2); + spacing = distance / pointDistance; + return spacing; +} + diff --git a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/QmitkUltrasoundSupport.h b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/QmitkUltrasoundSupport.h index 6be8dc1b45..65f1141a29 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/QmitkUltrasoundSupport.h +++ b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/QmitkUltrasoundSupport.h @@ -1,174 +1,185 @@ /*=================================================================== 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 QmitkUltrasoundSupport_h #define QmitkUltrasoundSupport_h #include #include #include #include #include "ui_QmitkUltrasoundSupportControls.h" #include "QmitkUSAbstractCustomWidget.h" #include "QmitkUSControlsBModeWidget.h" #include "QmitkUSControlsDopplerWidget.h" #include "QmitkUSControlsProbesWidget.h" #include #include "QmitkRenderWindow.h" #include #include #include #include #include /*! \brief UltrasoundSupport This plugin provides functionality to manage Ultrasound devices, create video devices and to view device images. \ingroup ${plugin_target}_internal */ class QmitkUltrasoundSupport : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: virtual void SetFocus() override; static const std::string VIEW_ID; virtual void CreateQtPartControl(QWidget *parent) override; QmitkUltrasoundSupport(); virtual ~QmitkUltrasoundSupport(); public slots: /* * \brief This is called when the newDeviceWidget is closed */ void OnNewDeviceWidgetDone(); protected slots: void OnClickedAddNewDevice(); void OnChangedFramerateLimit(); void OnClickedEditDevice(); /* *\brief Called, when the selection in the list of the active devices changes. */ void OnChangedActiveDevice(); void OnClickedFreezeButton(); void OnDeviceServiceEvent(const ctkServiceEvent event); /* * \brief This is the main imaging loop that updates the image and is called regularily during the imaging process */ void UpdateImage(); void RenderImage2d(); void RenderImage3d(); void StartTimers(); void StopTimers(); protected: void CreateControlWidgets(); void RemoveControlWidgets(); Ui::UltrasoundSupportControls* m_Controls; QmitkUSAbstractCustomWidget* m_ControlCustomWidget; QmitkUSControlsBModeWidget* m_ControlBModeWidget; QmitkUSControlsDopplerWidget* m_ControlDopplerWidget; QmitkUSControlsProbesWidget* m_ControlProbesWidget; bool m_ImageAlreadySetToNode; unsigned int m_CurrentImageWidth; unsigned int m_CurrentImageHeight; /** Keeps track of the amount of output Nodes*/ unsigned int m_AmountOfOutputs; /** The device that is currently used to aquire images */ mitk::USDevice::Pointer m_Device; void SetTimerIntervals(int intervalPipeline, int interval2D, int interval3D); /** This timer triggers periodic updates to the pipeline */ QTimer* m_UpdateTimer; QTimer* m_RenderingTimer2d; QTimer* m_RenderingTimer3d; /** These clocks are used to compute the framerate in the methods DisplayImage(),RenderImage2d() and RenderImage3d(). */ QTime m_Clock; QTime m_Clock2d; QTime m_Clock3d; /** A counter to comute the framerate. */ int m_FrameCounterPipeline; int m_FrameCounter2d; int m_FrameCounter3d; int m_FPSPipeline, m_FPS2d, m_FPS3d; /** Stores the properties of some QWidgets (and the tool storage file name) to QSettings.*/ void StoreUISettings(); /** Loads the properties of some QWidgets (and the tool storage file name) from QSettings.*/ void LoadUISettings(); /** The nodes that we feed images into.*/ std::vector m_Node; /** Adds a new node to the m_Nodes vector*/ void InitNewNode(); /** Destroys the last node in the m_Nodes vector */ void DestroyLastNode(); /** Checks the amount of slices in the image from the USDevice and creates as many Nodes as there are slices */ void UpdateAmountOfOutputs(); /** This function just checks how many nodes there are currently and sets the laser image to a jet transparent colormap. */ void UpdateLevelWindows(); bool m_ForceRequestUpdateAll; void SetColormap(mitk::DataNode::Pointer node, mitk::LookupTable::LookupTableType type); /** The seperated slices from m_Image */ std::vector m_curOutput; /** The old geometry of m_Image. It is needed to check if the geometry changed (e.g. because * the zoom factor was modified) and the image needs to be reinitialized. */ mitk::SlicedGeometry3D::Pointer m_OldGeometry; QList m_CustomWidgetServiceReference; double m_CurrentDynamicRange; + + /* Spacing calibration variables and methods */ + mitk::Point3D m_Xpoint1,m_Xpoint2,m_Ypoint1,m_Ypoint2; + double m_XSpacing, m_YSpacing; + double ComputeSpacing(mitk::Point3D p1, mitk::Point3D p2, double distance); + protected slots: + void SetXPoint1(); + void SetXPoint2(); + void SetYPoint1(); + void SetYPoint2(); + void WriteSpacingToDevice(); }; #endif // UltrasoundSupport_h diff --git a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/QmitkUltrasoundSupportControls.ui b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/QmitkUltrasoundSupportControls.ui index e6f442672a..945dcb4535 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/QmitkUltrasoundSupportControls.ui +++ b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/QmitkUltrasoundSupportControls.ui @@ -1,461 +1,683 @@ UltrasoundSupportControls 0 0 - 522 - 916 + 341 + 431 0 0 QmitkTemplate 15 15 15 15 true 8 50 false Qt::TabFocus 0 false false false :/USUI/ultrasound01-probe-300ppi.png :/USUI/ultrasound01-probe-300ppi.png:/USUI/ultrasound01-probe-300ppi.png Device Management 15 15 15 15 15 15 15 15 12 12 12 12 10 75 true Ultrasound Devices: 12 12 12 12 10 75 true Active Devices: 0 0 Show US image in MITK true Qt::Vertical 20 40 false :/USUI/ultrasound02-scan-300ppi.png :/USUI/ultrasound02-scan-72ppi-deactivated.png :/USUI/ultrasound02-scan-300ppi.png:/USUI/ultrasound02-scan-300ppi.png US Imaging Qt::Vertical 20 40 Qt::Horizontal Update Image Data Automatically true Freeze :/USUI/system-lock-screen.png:/USUI/system-lock-screen.png <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Framrate Settings:</span></p></body></html> Current overall Framerate: 0 FPS Image Pipeline Framerate Limit [FPS]: Qt::Horizontal 40 20 1 500 50 Update 2D View false false Qt::Horizontal 40 20 Framerate Limit [FPS]: 1 100 20 Update 3D View false Qt::Horizontal 18 20 Framerate Limit [FPS]: 1 100 5 + + + Spacing Calibration + + + + + + Along X-Axis: + + + + + + + + + Set First Point + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 999 + + + 50 + + + + + + + Distance [mm] + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Set Second Point + + + + + + + + + X Spacing: <na> + + + + + + + Qt::Horizontal + + + + + + + Along Y-Axis: + + + + + + + + + + + Set First Point + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 999 + + + 50 + + + + + + + Distance [mm] + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Set Second Point + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Y Spacing: <na> + + + + + + + Qt::Vertical + + + + 20 + 14 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Save Spacing To Device + + + + + + + QmitkUSDeviceManagerWidget QWidget
QmitkUSDeviceManagerWidget.h
1
QmitkUSNewVideoDeviceWidget QWidget
QmitkUSNewVideoDeviceWidget.h
1
QmitkServiceListWidget QWidget
QmitkServiceListWidget.h
1