diff --git a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/src/internal/QmitkMatchPointRegistrationEvaluator.cpp b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/src/internal/QmitkMatchPointRegistrationEvaluator.cpp index e70b85a35d..1974c893cb 100644 --- a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/src/internal/QmitkMatchPointRegistrationEvaluator.cpp +++ b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/src/internal/QmitkMatchPointRegistrationEvaluator.cpp @@ -1,331 +1,352 @@ /*=================================================================== 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 "mitkRegVisPropertyTags.h" #include "mitkMatchPointPropertyTags.h" #include "mitkRegEvaluationObject.h" #include "mitkRegistrationHelper.h" #include "mitkRegEvaluationMapper2D.h" #include // Qmitk #include "QmitkRenderWindow.h" #include "QmitkMatchPointRegistrationEvaluator.h" // Qt #include #include #include const std::string QmitkMatchPointRegistrationEvaluator::VIEW_ID = "org.mitk.views.matchpoint.registration.evaluator"; QmitkMatchPointRegistrationEvaluator::QmitkMatchPointRegistrationEvaluator() : m_Parent(NULL), m_activeEvaluation(false), m_autoMoving(false), m_autoTarget(false), m_currentSelectedTimeStep(0), HelperNodeName("RegistrationEvaluationHelper") { m_currentSelectedPosition.Fill(0.0); } QmitkMatchPointRegistrationEvaluator::~QmitkMatchPointRegistrationEvaluator() { if (this->m_selectedEvalNode.IsNotNull() && this->GetDataStorage().IsNotNull()) { this->GetDataStorage()->Remove(this->m_selectedEvalNode); } } void QmitkMatchPointRegistrationEvaluator::SetFocus() { } void QmitkMatchPointRegistrationEvaluator::Error(QString msg) { mitk::StatusBar::GetInstance()->DisplayErrorText(msg.toLatin1()); MITK_ERROR << msg.toStdString().c_str(); } void QmitkMatchPointRegistrationEvaluator::CreateQtPartControl(QWidget* parent) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); m_Parent = parent; connect(m_Controls.pbEval, SIGNAL(clicked()), this, SLOT(OnEvalBtnPushed())); connect(m_Controls.pbStop, SIGNAL(clicked()), this, SLOT(OnStopBtnPushed())); connect(m_Controls.evalSettings, SIGNAL(SettingsChanged(mitk::DataNode*)), this, SLOT(OnSettingsChanged(mitk::DataNode*))); this->m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart()); connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged())); m_selectedEvalNode = this->GetDataStorage()->GetNamedNode(HelperNodeName); this->CheckInputs(); this->ConfigureControls(); } void QmitkMatchPointRegistrationEvaluator::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) { this->m_SliceChangeListener.RenderWindowPartActivated(renderWindowPart); } void QmitkMatchPointRegistrationEvaluator::RenderWindowPartDeactivated( mitk::IRenderWindowPart* renderWindowPart) { this->m_SliceChangeListener.RenderWindowPartDeactivated(renderWindowPart); } void QmitkMatchPointRegistrationEvaluator::CheckInputs() { if (!m_activeEvaluation) { QList dataNodes = this->GetDataManagerSelection(); this->m_autoMoving = false; this->m_autoTarget = false; this->m_spSelectedMovingNode = NULL; this->m_spSelectedTargetNode = NULL; this->m_spSelectedRegNode = NULL; if (dataNodes.size() > 0) { //test if auto select works if (mitk::MITKRegistrationHelper::IsRegNode(dataNodes[0])) { this->m_spSelectedRegNode = dataNodes[0]; dataNodes.pop_front(); mitk::BaseProperty* uidProp = m_spSelectedRegNode->GetProperty(mitk::nodeProp_RegAlgMovingData); if (uidProp) { //search for the moving node mitk::NodePredicateProperty::Pointer predicate = mitk::NodePredicateProperty::New(mitk::nodeProp_UID, uidProp); this->m_spSelectedMovingNode = this->GetDataStorage()->GetNode(predicate); this->m_autoMoving = this->m_spSelectedMovingNode.IsNotNull(); } uidProp = m_spSelectedRegNode->GetProperty(mitk::nodeProp_RegAlgTargetData); if (uidProp) { //search for the target node mitk::NodePredicateProperty::Pointer predicate = mitk::NodePredicateProperty::New(mitk::nodeProp_UID, uidProp); this->m_spSelectedTargetNode = this->GetDataStorage()->GetNode(predicate); this->m_autoTarget = this->m_spSelectedTargetNode.IsNotNull(); } } //if still nodes are selected -> ignore possible auto select if (!dataNodes.empty()) { mitk::Image* inputImage = dynamic_cast(dataNodes[0]->GetData()); if (inputImage) { this->m_spSelectedMovingNode = dataNodes[0]; this->m_autoMoving = false; dataNodes.pop_front(); } } if (!dataNodes.empty()) { mitk::Image* inputImage = dynamic_cast(dataNodes[0]->GetData()); if (inputImage) { this->m_spSelectedTargetNode = dataNodes[0]; this->m_autoTarget = false; dataNodes.pop_front(); } } } } } void QmitkMatchPointRegistrationEvaluator::OnSelectionChanged(berry::IWorkbenchPart::Pointer source, const QList& nodes) { this->CheckInputs(); this->ConfigureControls(); }; + +void QmitkMatchPointRegistrationEvaluator::NodeRemoved(const mitk::DataNode* node) +{ + if (node == this->m_spSelectedMovingNode + || node == this->m_spSelectedRegNode + || node == this->m_spSelectedTargetNode + || node == this->m_selectedEvalNode) + { + if (node == this->m_selectedEvalNode) + { + this->m_selectedEvalNode = nullptr; + } + this->OnStopBtnPushed(); + MITK_INFO << "Stopped current MatchPoint evaluation session, because at least one relevant node was removed from storage."; + } +} + void QmitkMatchPointRegistrationEvaluator::ConfigureControls() { //configure input data widgets if (this->m_spSelectedRegNode.IsNull()) { if (this->m_spSelectedMovingNode.IsNotNull() && this->m_spSelectedTargetNode.IsNotNull()) { m_Controls.lbRegistrationName->setText( QString("No registration selected! Direct comparison")); } else { m_Controls.lbRegistrationName->setText( QString("No registration selected!")); } } else { m_Controls.lbRegistrationName->setText(QString::fromStdString( this->m_spSelectedRegNode->GetName())); } if (this->m_spSelectedMovingNode.IsNull()) { m_Controls.lbMovingName->setText(QString("no moving image selected!")); } else { if (this->m_autoMoving) { m_Controls.lbMovingName->setText(QString("") + QString::fromStdString( this->m_spSelectedMovingNode->GetName()) + QString(" (auto selected)")); } else { m_Controls.lbMovingName->setText(QString::fromStdString(this->m_spSelectedMovingNode->GetName())); } } if (this->m_spSelectedTargetNode.IsNull()) { m_Controls.lbTargetName->setText(QString("no target image selected!")); } else { if (this->m_autoTarget) { m_Controls.lbTargetName->setText(QString("") + QString::fromStdString( this->m_spSelectedTargetNode->GetName()) + QString(" (auto selected)")); } else { m_Controls.lbTargetName->setText(QString::fromStdString(this->m_spSelectedTargetNode->GetName())); } } //config settings widget this->m_Controls.evalSettings->setVisible(m_activeEvaluation); this->m_Controls.pbEval->setEnabled(this->m_spSelectedMovingNode.IsNotNull() && this->m_spSelectedTargetNode.IsNotNull()); this->m_Controls.pbEval->setVisible(!m_activeEvaluation); this->m_Controls.pbStop->setVisible(m_activeEvaluation); this->m_Controls.lbMovingName->setEnabled(!m_activeEvaluation); this->m_Controls.lbRegistrationName->setEnabled(!m_activeEvaluation); this->m_Controls.lbTargetName->setEnabled(!m_activeEvaluation); } void QmitkMatchPointRegistrationEvaluator::OnSliceChanged() { mitk::Point3D currentSelectedPosition = GetRenderWindowPart()->GetSelectedPosition(NULL); unsigned int currentSelectedTimeStep = GetRenderWindowPart()->GetTimeNavigationController()->GetTime()->GetPos(); if (m_currentSelectedPosition != currentSelectedPosition || m_currentSelectedTimeStep != currentSelectedTimeStep || m_selectedNodeTime > m_currentPositionTime) { //the current position has been changed or the selected node has been changed since the last position validation -> check position m_currentSelectedPosition = currentSelectedPosition; m_currentSelectedTimeStep = currentSelectedTimeStep; m_currentPositionTime.Modified(); if (this->m_selectedEvalNode.IsNotNull()) { this->m_selectedEvalNode->SetProperty(mitk::nodeProp_RegEvalCurrentPosition, mitk::GenericProperty::New(currentSelectedPosition)); } } } void QmitkMatchPointRegistrationEvaluator::OnSettingsChanged(mitk::DataNode*) { this->GetRenderWindowPart()->RequestUpdate(); }; void QmitkMatchPointRegistrationEvaluator::OnEvalBtnPushed() { //reinit view mitk::RenderingManager::GetInstance()->InitializeViews(m_spSelectedTargetNode->GetData()->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); mitk::RegEvaluationObject::Pointer regEval = mitk::RegEvaluationObject::New(); mitk::MAPRegistrationWrapper::Pointer reg; if (m_spSelectedRegNode.IsNotNull()) { reg = dynamic_cast(this->m_spSelectedRegNode->GetData()); } else { //generate a dymme reg to use reg = mitk::GenerateIdentityRegistration3D(); } regEval->SetRegistration(reg); regEval->SetTargetNode(this->m_spSelectedTargetNode); regEval->SetMovingNode(this->m_spSelectedMovingNode); if (this->m_selectedEvalNode.IsNotNull()) { this->GetDataStorage()->Remove(this->m_selectedEvalNode); } this->m_selectedEvalNode = mitk::DataNode::New(); this->m_selectedEvalNode->SetData(regEval); mitk::RegEvaluationMapper2D::SetDefaultProperties(this->m_selectedEvalNode); this->m_selectedEvalNode->SetName(HelperNodeName); this->m_selectedEvalNode->SetBoolProperty("helper object", true); this->GetDataStorage()->Add(this->m_selectedEvalNode); this->m_Controls.evalSettings->SetNode(this->m_selectedEvalNode); this->OnSliceChanged(); this->GetRenderWindowPart()->RequestUpdate(); this->m_activeEvaluation = true; this->CheckInputs(); this->ConfigureControls(); } void QmitkMatchPointRegistrationEvaluator::OnStopBtnPushed() { this->m_activeEvaluation = false; - this->GetDataStorage()->Remove(this->m_selectedEvalNode); + if (this->m_selectedEvalNode.IsNotNull()) + { + this->GetDataStorage()->Remove(this->m_selectedEvalNode); + } this->m_selectedEvalNode = nullptr; + this->m_Controls.evalSettings->SetNode(this->m_selectedEvalNode); this->CheckInputs(); this->ConfigureControls(); this->GetRenderWindowPart()->RequestUpdate(); } \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/src/internal/QmitkMatchPointRegistrationEvaluator.h b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/src/internal/QmitkMatchPointRegistrationEvaluator.h index db448a7e5a..d0536f01d4 100644 --- a/Plugins/org.mitk.gui.qt.matchpoint.evaluator/src/internal/QmitkMatchPointRegistrationEvaluator.h +++ b/Plugins/org.mitk.gui.qt.matchpoint.evaluator/src/internal/QmitkMatchPointRegistrationEvaluator.h @@ -1,122 +1,123 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __Q_MITK_MATCHPOINT_REGISTRATION_EVALUATOR_H #define __Q_MITK_MATCHPOINT_REGISTRATION_EVALUATOR_H #include #include #include #include "ui_QmitkMatchPointRegistrationEvaluator.h" /*! \brief QmitkMatchPointRegistrationEvaluator \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkFunctionality \ingroup ${plugin_target}_internal */ class QmitkMatchPointRegistrationEvaluator : public QmitkAbstractView, public mitk::IRenderWindowPartListener { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; /** * Creates smartpointer typedefs */ berryObjectMacro(QmitkMatchPointRegistrationEvaluator) QmitkMatchPointRegistrationEvaluator(); ~QmitkMatchPointRegistrationEvaluator(); virtual void CreateQtPartControl(QWidget *parent); protected slots: /// \brief Called when the user clicks the GUI button void OnEvalBtnPushed(); void OnStopBtnPushed(); void OnSettingsChanged(mitk::DataNode*); void OnSliceChanged(); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( berry::IWorkbenchPart::Pointer source, - const QList& nodes); + const QList& nodes) override; + + virtual void NodeRemoved(const mitk::DataNode* node) override; virtual void SetFocus(); virtual void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart); virtual void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart); Ui::MatchPointRegistrationEvaluatorControls m_Controls; private: QWidget *m_Parent; void Error(QString msg); /** Methods returns a list of all eval nodes in the data manager.*/ QList GetEvalNodes(); /** * Checks if appropriated nodes are selected in the data manager. If nodes are selected, * they are stored m_spSelectedRegNode, m_spSelectedInputNode and m_spSelectedRefNode. * They are also checked for vadility and stored in m_ValidInput,... . * It also sets the info lables accordingly.*/ void CheckInputs(); /** * Updates the state of controls regarding to selected eval object.*/ void ConfigureControls(); mitk::DataNode::Pointer m_selectedEvalNode; - mitk::DataStorage::SetOfObjects::ConstPointer m_evalNodes; QmitkSliceNavigationListener m_SliceChangeListener; itk::TimeStamp m_selectedNodeTime; itk::TimeStamp m_currentPositionTime; /** @brief currently valid selected position in the inspector*/ mitk::Point3D m_currentSelectedPosition; /** @brief indicates if the currently selected position is valid for the currently selected fit. * This it is within the input image */ unsigned int m_currentSelectedTimeStep; mitk::DataNode::Pointer m_spSelectedRegNode; mitk::DataNode::Pointer m_spSelectedMovingNode; mitk::DataNode::Pointer m_spSelectedTargetNode; bool m_autoTarget; bool m_autoMoving; bool m_activeEvaluation; const std::string HelperNodeName; }; #endif // MatchPoint_h diff --git a/Plugins/org.mitk.gui.qt.matchpoint.manipulator/src/internal/QmitkMatchPointRegistrationManipulator.cpp b/Plugins/org.mitk.gui.qt.matchpoint.manipulator/src/internal/QmitkMatchPointRegistrationManipulator.cpp index e0c3b80927..920612773f 100644 --- a/Plugins/org.mitk.gui.qt.matchpoint.manipulator/src/internal/QmitkMatchPointRegistrationManipulator.cpp +++ b/Plugins/org.mitk.gui.qt.matchpoint.manipulator/src/internal/QmitkMatchPointRegistrationManipulator.cpp @@ -1,727 +1,747 @@ /*=================================================================== 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 "mitkRegVisPropertyTags.h" #include "mitkMatchPointPropertyTags.h" #include "mitkRegEvaluationObject.h" #include "mitkRegistrationHelper.h" #include "mitkRegEvaluationMapper2D.h" #include #include #include // Qmitk #include "QmitkRenderWindow.h" #include "QmitkMatchPointRegistrationManipulator.h" #include // Qt #include #include #include #include //MatchPoint #include #include #include #include #include #include #include const std::string QmitkMatchPointRegistrationManipulator::VIEW_ID = "org.mitk.views.matchpoint.registration.manipulator"; QmitkMatchPointRegistrationManipulator::QmitkMatchPointRegistrationManipulator() : m_Parent(NULL), m_activeManipulation(false), m_autoMoving(false), m_autoTarget(false), m_currentSelectedTimeStep(0), HelperNodeName("RegistrationManipulationEvaluationHelper"), m_internalUpdate(false) { m_currentSelectedPosition.Fill(0.0); } QmitkMatchPointRegistrationManipulator::~QmitkMatchPointRegistrationManipulator() { if (this->m_EvalNode.IsNotNull() && this->GetDataStorage().IsNotNull()) { this->GetDataStorage()->Remove(this->m_EvalNode); } } void QmitkMatchPointRegistrationManipulator::SetFocus() { } void QmitkMatchPointRegistrationManipulator::Error(QString msg) { mitk::StatusBar::GetInstance()->DisplayErrorText(msg.toLatin1()); MITK_ERROR << msg.toStdString().c_str(); } void QmitkMatchPointRegistrationManipulator::CreateQtPartControl(QWidget* parent) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); m_Parent = parent; connect(m_Controls.pbStart, SIGNAL(clicked()), this, SLOT(OnStartBtnPushed())); connect(m_Controls.pbCancel, SIGNAL(clicked()), this, SLOT(OnCancelBtnPushed())); connect(m_Controls.pbStore, SIGNAL(clicked()), this, SLOT(OnStoreBtnPushed())); connect(m_Controls.evalSettings, SIGNAL(SettingsChanged(mitk::DataNode*)), this, SLOT(OnSettingsChanged(mitk::DataNode*))); connect(m_Controls.radioSelectedReg, SIGNAL(toggled(bool)), m_Controls.lbRegistrationName, SLOT(setVisible(bool))); connect(m_Controls.slideRotX, SIGNAL(valueChanged(int)), this, SLOT(OnRotXSlideChanged(int))); connect(m_Controls.sbRotX, SIGNAL(valueChanged(double)), this, SLOT(OnRotXChanged(double))); connect(m_Controls.slideRotY, SIGNAL(valueChanged(int)), this, SLOT(OnRotYSlideChanged(int))); connect(m_Controls.sbRotY, SIGNAL(valueChanged(double)), this, SLOT(OnRotYChanged(double))); connect(m_Controls.slideRotZ, SIGNAL(valueChanged(int)), this, SLOT(OnRotZSlideChanged(int))); connect(m_Controls.sbRotZ, SIGNAL(valueChanged(double)), this, SLOT(OnRotZChanged(double))); connect(m_Controls.slideTransX, SIGNAL(valueChanged(int)), this, SLOT(OnTransXSlideChanged(int))); connect(m_Controls.sbTransX, SIGNAL(valueChanged(double)), this, SLOT(OnTransXChanged(double))); connect(m_Controls.slideTransY, SIGNAL(valueChanged(int)), this, SLOT(OnTransYSlideChanged(int))); connect(m_Controls.sbTransY, SIGNAL(valueChanged(double)), this, SLOT(OnTransYChanged(double))); connect(m_Controls.slideTransZ, SIGNAL(valueChanged(int)), this, SLOT(OnTransZSlideChanged(int))); connect(m_Controls.sbTransZ, SIGNAL(valueChanged(double)), this, SLOT(OnTransZChanged(double))); connect(m_Controls.comboCenter, SIGNAL(currentIndexChanged(int)), this, SLOT(OnCenterTypeChanged(int))); this->m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart()); connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged())); m_Controls.radioNewReg->setChecked(true); m_Controls.groupScale->setVisible(false); m_Controls.lbRegistrationName->setVisible(false); m_EvalNode = this->GetDataStorage()->GetNamedNode(HelperNodeName); this->CheckInputs(); this->StopSession(); this->ConfigureControls(); } void QmitkMatchPointRegistrationManipulator::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) { this->m_SliceChangeListener.RenderWindowPartActivated(renderWindowPart); } void QmitkMatchPointRegistrationManipulator::RenderWindowPartDeactivated( mitk::IRenderWindowPart* renderWindowPart) { this->m_SliceChangeListener.RenderWindowPartDeactivated(renderWindowPart); } void QmitkMatchPointRegistrationManipulator::CheckInputs() { if (!m_activeManipulation) { QList dataNodes = this->GetDataManagerSelection(); this->m_autoMoving = false; this->m_autoTarget = false; this->m_SelectedMovingNode = NULL; this->m_SelectedTargetNode = NULL; this->m_SelectedPreRegNode = NULL; this->m_SelectedPreReg = NULL; if (dataNodes.size() > 0) { //test if auto select works if (mitk::MITKRegistrationHelper::IsRegNode(dataNodes[0])) { mitk::DataNode::Pointer regNode = dataNodes[0]; dataNodes.pop_front(); mitk::MAPRegistrationWrapper* regWrapper = dynamic_cast(regNode->GetData()); if (regWrapper) { this->m_SelectedPreReg = dynamic_cast(regWrapper->GetRegistration()); } if (this->m_SelectedPreReg.IsNotNull()) { this->m_SelectedPreRegNode = regNode; mitk::BaseProperty* uidProp = m_SelectedPreRegNode->GetProperty(mitk::nodeProp_RegAlgMovingData); if (uidProp) { //search for the moving node mitk::NodePredicateProperty::Pointer predicate = mitk::NodePredicateProperty::New(mitk::nodeProp_UID, uidProp); this->m_SelectedMovingNode = this->GetDataStorage()->GetNode(predicate); this->m_autoMoving = this->m_SelectedMovingNode.IsNotNull(); } uidProp = m_SelectedPreRegNode->GetProperty(mitk::nodeProp_RegAlgTargetData); if (uidProp) { //search for the target node mitk::NodePredicateProperty::Pointer predicate = mitk::NodePredicateProperty::New(mitk::nodeProp_UID, uidProp); this->m_SelectedTargetNode = this->GetDataStorage()->GetNode(predicate); this->m_autoTarget = this->m_SelectedTargetNode.IsNotNull(); } } } //if still nodes are selected -> ignore possible auto select if (!dataNodes.empty()) { mitk::Image* inputImage = dynamic_cast(dataNodes[0]->GetData()); if (inputImage) { this->m_SelectedMovingNode = dataNodes[0]; this->m_autoMoving = false; dataNodes.pop_front(); } } if (!dataNodes.empty()) { mitk::Image* inputImage = dynamic_cast(dataNodes[0]->GetData()); if (inputImage) { this->m_SelectedTargetNode = dataNodes[0]; this->m_autoTarget = false; dataNodes.pop_front(); } } } } } void QmitkMatchPointRegistrationManipulator::OnSelectionChanged(berry::IWorkbenchPart::Pointer source, const QList& nodes) { this->CheckInputs(); this->ConfigureControls(); }; + +void QmitkMatchPointRegistrationManipulator::NodeRemoved(const mitk::DataNode* node) +{ + if (node == this->m_SelectedMovingNode + || node == this->m_SelectedTargetNode + || node == this->m_EvalNode) + { + if (node == this->m_EvalNode) + { + this->m_EvalNode = nullptr; + } + this->OnCancelBtnPushed(); + MITK_INFO << "Stopped current MatchPoint manual registration session, because at least one relevant node was removed from storage."; + } +} + void QmitkMatchPointRegistrationManipulator::ConfigureControls() { //configure input data widgets if (this->m_SelectedPreRegNode.IsNull()) { m_Controls.lbRegistrationName->setText( QString("No registration selected!")); } else { m_Controls.lbRegistrationName->setText(QString::fromStdString( this->m_SelectedPreRegNode->GetName())); } if (this->m_SelectedMovingNode.IsNull()) { m_Controls.lbMovingName->setText(QString("no moving image selected!")); } else { if (this->m_autoMoving) { m_Controls.lbMovingName->setText(QString("") + QString::fromStdString( this->m_SelectedMovingNode->GetName()) + QString(" (auto selected)")); } else { m_Controls.lbMovingName->setText(QString::fromStdString(this->m_SelectedMovingNode->GetName())); } } if (this->m_SelectedTargetNode.IsNull()) { m_Controls.lbTargetName->setText(QString("no target image selected!")); } else { if (this->m_autoTarget) { m_Controls.lbTargetName->setText(QString("") + QString::fromStdString( this->m_SelectedTargetNode->GetName()) + QString(" (auto selected)")); } else { m_Controls.lbTargetName->setText(QString::fromStdString(this->m_SelectedTargetNode->GetName())); } } if (!m_activeManipulation) { QString name = "ManuelRegistration"; if (m_SelectedPreRegNode.IsNotNull()) { name = QString::fromStdString(m_SelectedPreRegNode->GetName()) + " manual refined"; } this->m_Controls.lbNewRegName->setText(name); } //config settings widget this->m_Controls.groupReg->setEnabled(!m_activeManipulation); this->m_Controls.lbMovingName->setEnabled(!m_activeManipulation); this->m_Controls.lbTargetName->setEnabled(!m_activeManipulation); this->m_Controls.pbStart->setEnabled(this->m_SelectedMovingNode.IsNotNull() && this->m_SelectedTargetNode.IsNotNull() && !m_activeManipulation); this->m_Controls.lbNewRegName->setEnabled(m_activeManipulation); this->m_Controls.checkMapEntity->setEnabled(m_activeManipulation); this->m_Controls.tabWidget->setEnabled(m_activeManipulation); this->m_Controls.pbCancel->setEnabled(m_activeManipulation); this->m_Controls.pbStore->setEnabled(m_activeManipulation); this->UpdateTransformWidgets(); } void QmitkMatchPointRegistrationManipulator::InitSession() { this->m_InverseCurrentTransform = TransformType::New(); this->m_InverseCurrentTransform->SetIdentity(); this->m_DirectCurrentTransform = TransformType::New(); this->m_DirectCurrentTransform->SetIdentity(); this->m_CurrentRegistrationWrapper = mitk::MAPRegistrationWrapper::New(); m_CurrentRegistration = MAPRegistrationType::New(); this->m_CurrentRegistrationWrapper->SetRegistration(m_CurrentRegistration); ::map::core::RegistrationManipulator manipulator(m_CurrentRegistration); ::map::core::PreCachedRegistrationKernel<3, 3>::Pointer kernel = ::map::core::PreCachedRegistrationKernel<3, 3>::New(); manipulator.setDirectMapping(::map::core::NullRegistrationKernel < 3, 3 >::New()); if (this->m_Controls.radioNewReg->isChecked()) { //new registration kernel->setTransformModel(m_InverseCurrentTransform); manipulator.setInverseMapping(kernel); //init to map the image centers auto movingCenter = m_SelectedMovingNode->GetData()->GetTimeGeometry()->GetCenterInWorld(); auto targetCenter = m_SelectedTargetNode->GetData()->GetTimeGeometry()->GetCenterInWorld(); auto offset = targetCenter - movingCenter; m_DirectCurrentTransform->SetOffset(offset); m_DirectCurrentTransform->GetInverse(m_InverseCurrentTransform); } else { //use selected pre registration as baseline itk::CompositeTransform < ::map::core::continuous::ScalarType, 3>::Pointer compTransform = itk::CompositeTransform < ::map::core::continuous::ScalarType, 3>::New(); const map::core::RegistrationKernel<3, 3>* preKernel = dynamic_cast*>(&this->m_SelectedPreReg->getInverseMapping()); compTransform->AddTransform(preKernel->getTransformModel()->Clone()); compTransform->AddTransform(this->m_InverseCurrentTransform); kernel->setTransformModel(compTransform); manipulator.setInverseMapping(kernel); } m_Controls.comboCenter->setCurrentIndex(0); this->ConfigureTransformCenter(0); //set bounds of the translation slider widget to have sensible ranges auto currenttrans = m_DirectCurrentTransform->GetTranslation(); this->m_Controls.slideTransX->setMinimum(currenttrans[0] - 250); this->m_Controls.slideTransY->setMinimum(currenttrans[1] - 250); this->m_Controls.slideTransZ->setMinimum(currenttrans[2] - 250); this->m_Controls.slideTransX->setMaximum(currenttrans[0] + 250); this->m_Controls.slideTransY->setMaximum(currenttrans[1] + 250); this->m_Controls.slideTransZ->setMaximum(currenttrans[2] + 250); //reinit view mitk::RenderingManager::GetInstance()->InitializeViews(m_SelectedTargetNode->GetData()->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); //generate evaluation node mitk::RegEvaluationObject::Pointer regEval = mitk::RegEvaluationObject::New(); regEval->SetRegistration(this->m_CurrentRegistrationWrapper); regEval->SetTargetNode(this->m_SelectedTargetNode); regEval->SetMovingNode(this->m_SelectedMovingNode); this->m_EvalNode = mitk::DataNode::New(); this->m_EvalNode->SetData(regEval); mitk::RegEvaluationMapper2D::SetDefaultProperties(this->m_EvalNode); this->m_EvalNode->SetName(HelperNodeName); this->m_EvalNode->SetBoolProperty("helper object", true); this->GetDataStorage()->Add(this->m_EvalNode); this->m_Controls.evalSettings->SetNode(this->m_EvalNode); this->m_activeManipulation = true; }; void QmitkMatchPointRegistrationManipulator::StopSession() { this->m_InverseCurrentTransform = TransformType::New(); this->m_InverseCurrentTransform->SetIdentity(); this->m_DirectCurrentTransform = TransformType::New(); this->m_DirectCurrentTransform->SetIdentity(); this->m_CurrentRegistration = nullptr; this->m_CurrentRegistrationWrapper = nullptr; - this->GetDataStorage()->Remove(this->m_EvalNode); + if (this->m_EvalNode.IsNotNull()) + { + this->GetDataStorage()->Remove(this->m_EvalNode); + } + this->m_EvalNode = nullptr; this->m_activeManipulation = false; }; void QmitkMatchPointRegistrationManipulator::UpdateTransformWidgets() { this->m_internalUpdate = true; this->m_Controls.sbTransX->setValue(this->m_DirectCurrentTransform->GetTranslation()[0]); this->m_Controls.sbTransY->setValue(this->m_DirectCurrentTransform->GetTranslation()[1]); this->m_Controls.sbTransZ->setValue(this->m_DirectCurrentTransform->GetTranslation()[2]); this->m_Controls.slideTransX->setValue(this->m_DirectCurrentTransform->GetTranslation()[0]); this->m_Controls.slideTransY->setValue(this->m_DirectCurrentTransform->GetTranslation()[1]); this->m_Controls.slideTransZ->setValue(this->m_DirectCurrentTransform->GetTranslation()[2]); this->m_Controls.sbRotX->setValue(this->m_DirectCurrentTransform->GetAngleX()*(180 / boost::math::double_constants::pi)); this->m_Controls.sbRotY->setValue(this->m_DirectCurrentTransform->GetAngleY()*(180 / boost::math::double_constants::pi)); this->m_Controls.sbRotZ->setValue(this->m_DirectCurrentTransform->GetAngleZ()*(180 / boost::math::double_constants::pi)); this->m_Controls.slideRotX->setValue(this->m_DirectCurrentTransform->GetAngleX()*(180 / boost::math::double_constants::pi)); this->m_Controls.slideRotY->setValue(this->m_DirectCurrentTransform->GetAngleY()*(180 / boost::math::double_constants::pi)); this->m_Controls.slideRotZ->setValue(this->m_DirectCurrentTransform->GetAngleZ()*(180 / boost::math::double_constants::pi)); this->m_internalUpdate = false; }; void QmitkMatchPointRegistrationManipulator::UpdateTransform(bool updateRotation) { if (updateRotation) { if (m_Controls.comboCenter->currentIndex() == 2) { ConfigureTransformCenter(2); } this->m_DirectCurrentTransform->SetRotation(this->m_Controls.sbRotX->value()*(boost::math::double_constants::pi / 180), this->m_Controls.sbRotY->value()*(boost::math::double_constants::pi / 180), this->m_Controls.sbRotZ->value()*(boost::math::double_constants::pi / 180)); } else { TransformType::OutputVectorType trans; trans[0] = this->m_Controls.sbTransX->value(); trans[1] = this->m_Controls.sbTransY->value(); trans[2] = this->m_Controls.sbTransZ->value(); this->m_DirectCurrentTransform->SetTranslation(trans); } this->m_DirectCurrentTransform->GetInverse(this->m_InverseCurrentTransform); this->UpdateTransformWidgets(); this->m_EvalNode->Modified(); this->m_CurrentRegistrationWrapper->Modified(); this->GetRenderWindowPart()->RequestUpdate(); }; void QmitkMatchPointRegistrationManipulator::OnSliceChanged() { mitk::Point3D currentSelectedPosition = GetRenderWindowPart()->GetSelectedPosition(NULL); unsigned int currentSelectedTimeStep = GetRenderWindowPart()->GetTimeNavigationController()->GetTime()->GetPos(); if (m_currentSelectedPosition != currentSelectedPosition || m_currentSelectedTimeStep != currentSelectedTimeStep || m_selectedNodeTime > m_currentPositionTime) { //the current position has been changed or the selected node has been changed since the last position validation -> check position m_currentSelectedPosition = currentSelectedPosition; m_currentSelectedTimeStep = currentSelectedTimeStep; m_currentPositionTime.Modified(); if (this->m_EvalNode.IsNotNull()) { this->m_EvalNode->SetProperty(mitk::nodeProp_RegEvalCurrentPosition, mitk::GenericProperty::New(currentSelectedPosition)); } if (m_activeManipulation && m_Controls.comboCenter->currentIndex() == 2) { //update transform with the current position. OnCenterTypeChanged(m_Controls.comboCenter->currentIndex()); } } } void QmitkMatchPointRegistrationManipulator::OnSettingsChanged(mitk::DataNode*) { this->GetRenderWindowPart()->RequestUpdate(); }; void QmitkMatchPointRegistrationManipulator::OnStartBtnPushed() { this->InitSession(); this->OnSliceChanged(); this->GetRenderWindowPart()->RequestUpdate(); this->CheckInputs(); this->ConfigureControls(); } void QmitkMatchPointRegistrationManipulator::OnCancelBtnPushed() { this->StopSession(); this->CheckInputs(); this->ConfigureControls(); this->GetRenderWindowPart()->RequestUpdate(); } void QmitkMatchPointRegistrationManipulator::OnStoreBtnPushed() { mitk::MAPRegistrationWrapper::Pointer newRegWrapper = mitk::MAPRegistrationWrapper::New(); MAPRegistrationType::Pointer newReg = MAPRegistrationType::New(); newRegWrapper->SetRegistration(newReg); ::map::core::RegistrationManipulator manipulator(newReg); ::map::core::PreCachedRegistrationKernel<3, 3>::Pointer kernel = ::map::core::PreCachedRegistrationKernel<3, 3>::New(); kernel->setTransformModel(m_InverseCurrentTransform); ::map::core::PreCachedRegistrationKernel<3, 3>::Pointer kernel2 = ::map::core::PreCachedRegistrationKernel<3, 3>::New(); kernel2->setTransformModel(m_InverseCurrentTransform->GetInverseTransform()); manipulator.setInverseMapping(kernel); manipulator.setDirectMapping(kernel2); if (this->m_Controls.radioSelectedReg->isChecked()) { //compine registration with selected pre registration as baseline typedef ::map::core::RegistrationCombinator CombinatorType; CombinatorType::Pointer combinator = CombinatorType::New(); newReg = combinator->process(*m_SelectedPreReg,*newReg); newRegWrapper->SetRegistration(newReg); } mitk::DataNode::Pointer spResultRegistrationNode = mitk::generateRegistrationResultNode( this->m_Controls.lbNewRegName->text().toStdString(), newRegWrapper, "org.mitk::manual_registration", mitk::EnsureUID(m_SelectedMovingNode), mitk::EnsureUID(m_SelectedTargetNode)); this->GetDataStorage()->Add(spResultRegistrationNode); if (m_Controls.checkMapEntity->checkState() == Qt::Checked) { QmitkMappingJob* pMapJob = new QmitkMappingJob(); pMapJob->setAutoDelete(true); pMapJob->m_spInputData = this->m_SelectedMovingNode->GetData(); pMapJob->m_InputNodeUID = mitk::EnsureUID(m_SelectedMovingNode); pMapJob->m_spRegNode = spResultRegistrationNode; pMapJob->m_doGeometryRefinement = false; pMapJob->m_spRefGeometry = this->m_SelectedTargetNode->GetData()->GetGeometry()->Clone().GetPointer(); pMapJob->m_MappedName = this->m_Controls.lbNewRegName->text().toStdString() + std::string(" mapped moving data"); pMapJob->m_allowUndefPixels = true; pMapJob->m_paddingValue = 100; pMapJob->m_allowUnregPixels = true; pMapJob->m_errorValue = 200; pMapJob->m_InterpolatorLabel = "Linear Interpolation"; pMapJob->m_InterpolatorType = mitk::ImageMappingInterpolator::Linear; connect(pMapJob, SIGNAL(Error(QString)), this, SLOT(OnMapJobError(QString))); connect(pMapJob, SIGNAL(MapResultIsAvailable(mitk::BaseData::Pointer, const QmitkMappingJob*)), this, SLOT(OnMapResultIsAvailable(mitk::BaseData::Pointer, const QmitkMappingJob*)), Qt::BlockingQueuedConnection); QThreadPool* threadPool = QThreadPool::globalInstance(); threadPool->start(pMapJob); } this->StopSession(); this->CheckInputs(); this->ConfigureControls(); this->GetRenderWindowPart()->RequestUpdate(); } void QmitkMatchPointRegistrationManipulator::OnMapResultIsAvailable(mitk::BaseData::Pointer spMappedData, const QmitkMappingJob* job) { mitk::DataNode::Pointer spMappedNode = mitk::generateMappedResultNode(job->m_MappedName, spMappedData, job->GetRegistration()->getRegistrationUID(), job->m_InputNodeUID, job->m_doGeometryRefinement, job->m_InterpolatorLabel); this->GetDataStorage()->Add(spMappedNode); this->GetRenderWindowPart()->RequestUpdate(); }; void QmitkMatchPointRegistrationManipulator::OnRotXChanged(double x) { if (!m_internalUpdate) { m_internalUpdate = true; this->m_Controls.slideRotX->setValue(x); m_internalUpdate = false; this->UpdateTransform(true); } }; void QmitkMatchPointRegistrationManipulator::OnRotXSlideChanged(int x) { if (!m_internalUpdate) { this->m_Controls.sbRotX->setValue(x); } }; void QmitkMatchPointRegistrationManipulator::OnRotYChanged(double y) { if (!m_internalUpdate) { m_internalUpdate = true; this->m_Controls.slideRotY->setValue(y); m_internalUpdate = false; this->UpdateTransform(true); } }; void QmitkMatchPointRegistrationManipulator::OnRotYSlideChanged(int y) { if (!m_internalUpdate) { this->m_Controls.sbRotY->setValue(y); } }; void QmitkMatchPointRegistrationManipulator::OnRotZChanged(double z) { if (!m_internalUpdate) { m_internalUpdate = true; this->m_Controls.slideRotZ->setValue(z); m_internalUpdate = false; this->UpdateTransform(true); } }; void QmitkMatchPointRegistrationManipulator::OnRotZSlideChanged(int z) { if (!m_internalUpdate) { this->m_Controls.sbRotZ->setValue(z); } }; void QmitkMatchPointRegistrationManipulator::OnTransXChanged(double x) { if (!m_internalUpdate) { m_internalUpdate = true; this->m_Controls.slideTransX->setValue(x); m_internalUpdate = false; this->UpdateTransform(); } }; void QmitkMatchPointRegistrationManipulator::OnTransXSlideChanged(int x) { if (!m_internalUpdate) { this->m_Controls.sbTransX->setValue(x); } }; void QmitkMatchPointRegistrationManipulator::OnTransYChanged(double y) { if (!m_internalUpdate) { m_internalUpdate = true; this->m_Controls.slideTransY->setValue(y); m_internalUpdate = false; this->UpdateTransform(); } }; void QmitkMatchPointRegistrationManipulator::OnTransYSlideChanged(int y) { if (!m_internalUpdate) { this->m_Controls.sbTransY->setValue(y); } }; void QmitkMatchPointRegistrationManipulator::OnTransZChanged(double z) { if (!m_internalUpdate) { m_internalUpdate = true; this->m_Controls.slideTransZ->setValue(z); m_internalUpdate = false; this->UpdateTransform(); } }; void QmitkMatchPointRegistrationManipulator::OnTransZSlideChanged(int z) { if (!m_internalUpdate) { this->m_Controls.sbTransZ->setValue(z); } }; void QmitkMatchPointRegistrationManipulator::OnCenterTypeChanged(int index) { ConfigureTransformCenter(index); this->UpdateTransformWidgets(); if (this->m_EvalNode.IsNotNull()) { this->m_EvalNode->Modified(); } this->m_CurrentRegistrationWrapper->Modified(); this->GetRenderWindowPart()->RequestUpdate(); }; void QmitkMatchPointRegistrationManipulator::ConfigureTransformCenter(int centerType) { auto offset = m_DirectCurrentTransform->GetOffset(); if (centerType == 0) { //image center auto center = m_SelectedMovingNode->GetData()->GetTimeGeometry()->GetCenterInWorld(); m_DirectCurrentTransform->SetCenter(center); } else if (centerType == 1) { //world origin TransformType::OutputPointType itkCenter; itkCenter.Fill(0.0); m_DirectCurrentTransform->SetCenter(itkCenter); } else { //current selected point auto newCenter = m_InverseCurrentTransform->TransformPoint(m_currentSelectedPosition); m_DirectCurrentTransform->SetCenter(newCenter); } m_DirectCurrentTransform->SetOffset(offset); m_DirectCurrentTransform->GetInverse(m_InverseCurrentTransform); }; diff --git a/Plugins/org.mitk.gui.qt.matchpoint.manipulator/src/internal/QmitkMatchPointRegistrationManipulator.h b/Plugins/org.mitk.gui.qt.matchpoint.manipulator/src/internal/QmitkMatchPointRegistrationManipulator.h index e8e244b7bd..4450abb0f0 100644 --- a/Plugins/org.mitk.gui.qt.matchpoint.manipulator/src/internal/QmitkMatchPointRegistrationManipulator.h +++ b/Plugins/org.mitk.gui.qt.matchpoint.manipulator/src/internal/QmitkMatchPointRegistrationManipulator.h @@ -1,173 +1,175 @@ /*=================================================================== 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 __Q_MITK_MATCHPOINT_REGISTRATION_MANIPULATOR_H #define __Q_MITK_MATCHPOINT_REGISTRATION_MANIPULATOR_H #include #include #include #include #include #include "ui_QmitkMatchPointRegistrationManipulator.h" class QmitkMappingJob; /*! \brief QmitkMatchPointRegistrationManipulator \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkFunctionality \ingroup ${plugin_target}_internal */ class QmitkMatchPointRegistrationManipulator : public QmitkAbstractView, public mitk::IRenderWindowPartListener { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; /** * Creates smartpointer typedefs */ berryObjectMacro(QmitkMatchPointRegistrationManipulator) QmitkMatchPointRegistrationManipulator(); ~QmitkMatchPointRegistrationManipulator(); virtual void CreateQtPartControl(QWidget *parent); protected slots: /// \brief Called when the user clicks the GUI button void OnStartBtnPushed(); void OnCancelBtnPushed(); void OnStoreBtnPushed(); void OnSettingsChanged(mitk::DataNode*); void OnRotXChanged(double); void OnRotYChanged(double); void OnRotZChanged(double); void OnTransXChanged(double); void OnTransYChanged(double); void OnTransZChanged(double); void OnRotXSlideChanged(int); void OnRotYSlideChanged(int); void OnRotZSlideChanged(int); void OnTransXSlideChanged(int); void OnTransYSlideChanged(int); void OnTransZSlideChanged(int); void OnCenterTypeChanged(int); void OnSliceChanged(); void OnMapResultIsAvailable(mitk::BaseData::Pointer spMappedData, const QmitkMappingJob* job); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( berry::IWorkbenchPart::Pointer source, - const QList& nodes); + const QList& nodes) override; + + virtual void NodeRemoved(const mitk::DataNode* node) override; virtual void SetFocus(); virtual void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart); virtual void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart); Ui::MatchPointRegistrationManipulatorControls m_Controls; private: QWidget *m_Parent; void Error(QString msg); /** Methods returns a list of all eval nodes in the data manager.*/ QList GetEvalNodes(); /** * Checks if appropriated nodes are selected in the data manager. If nodes are selected, * they are stored m_spSelectedRegNode, m_spSelectedInputNode and m_spSelectedRefNode. * They are also checked for vadility.*/ void CheckInputs(); /** * Updates the state of controls regarding to the state of the view and it objects.*/ void ConfigureControls(); /** Initialize the state of the view, so the manipulation can start.*/ void InitSession(); /** Stops session, removes all obsolite members (e.g. RegEvalObject). After that the view is in a valid but inactive state.*/ void StopSession(); /** * Updates the widgets that manipulate the transform according to the transform.*/ void UpdateTransformWidgets(); /** * Updates the transform according to the widgets that manipulate the transform.*/ void UpdateTransform(bool updateRotation = false); void ConfigureTransformCenter(int centerType); mitk::DataNode::Pointer m_EvalNode; QmitkSliceNavigationListener m_SliceChangeListener; itk::TimeStamp m_selectedNodeTime; itk::TimeStamp m_currentPositionTime; /** @brief currently valid selected position in the inspector*/ mitk::Point3D m_currentSelectedPosition; /** @brief indicates if the currently selected position is valid for the currently selected fit. * This it is within the input image */ unsigned int m_currentSelectedTimeStep; mitk::DataNode::Pointer m_SelectedPreRegNode; mitk::DataNode::Pointer m_SelectedMovingNode; mitk::DataNode::Pointer m_SelectedTargetNode; mitk::MAPRegistrationWrapper::Pointer m_CurrentRegistrationWrapper; typedef itk::Euler3DTransform<::map::core::continuous::ScalarType> TransformType; TransformType::Pointer m_InverseCurrentTransform; TransformType::Pointer m_DirectCurrentTransform; typedef map::core::Registration<3, 3> MAPRegistrationType; MAPRegistrationType::Pointer m_CurrentRegistration; MAPRegistrationType::ConstPointer m_SelectedPreReg; bool m_autoTarget; bool m_autoMoving; bool m_activeManipulation; bool m_internalUpdate; const std::string HelperNodeName; }; #endif // MatchPoint_h