diff --git a/Modules/Multilabel/files.cmake b/Modules/Multilabel/files.cmake index bde04e5e6f..6f267f401b 100644 --- a/Modules/Multilabel/files.cmake +++ b/Modules/Multilabel/files.cmake @@ -1,19 +1,20 @@ set(CPP_FILES mitkLabel.cpp mitkLabelSet.cpp mitkLabelSetImage.cpp mitkLabelSetImageConverter.cpp mitkLabelSetImageSource.cpp + mitkLabelSetImageHelper.cpp mitkLabelSetImageSurfaceStampFilter.cpp mitkLabelSetImageToSurfaceFilter.cpp mitkLabelSetImageToSurfaceThreadedFilter.cpp mitkLabelSetImageVtkMapper2D.cpp mitkMultilabelObjectFactory.cpp mitkLabelSetIOHelper.cpp mitkDICOMSegmentationPropertyHelper.cpp mitkDICOMSegmentationConstants.cpp ) set(RESOURCE_FILES ) diff --git a/Modules/Multilabel/mitkLabelSetImageHelper.cpp b/Modules/Multilabel/mitkLabelSetImageHelper.cpp new file mode 100644 index 0000000000..8b4eaed591 --- /dev/null +++ b/Modules/Multilabel/mitkLabelSetImageHelper.cpp @@ -0,0 +1,77 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include + +#include +#include +#include + +mitk::DataNode::Pointer mitk::LabelSetImageHelper::CreateNewSegmentationNode(const DataNode* referenceNode, + const Image* initialSegmentationImage, const std::string& segmentationName) +{ + std::string newSegmentationName = segmentationName; + if (newSegmentationName.empty()) + { + newSegmentationName = referenceNode->GetName(); + newSegmentationName.append("-labels"); + } + + if (nullptr == initialSegmentationImage) + { + return nullptr; + } + + auto newLabelSetImage = mitk::LabelSetImage::New(); + try + { + newLabelSetImage->Initialize(initialSegmentationImage); + } + catch (mitk::Exception &e) + { + mitkReThrow(e) << "Could not initialize new label set image."; + return nullptr; + } + + auto newSegmentationNode = mitk::DataNode::New(); + newSegmentationNode->SetData(newLabelSetImage); + newSegmentationNode->SetName(newSegmentationName); + + // set additional image information + newLabelSetImage->GetExteriorLabel()->SetProperty("name.parent", mitk::StringProperty::New(referenceNode->GetName())); + newLabelSetImage->GetExteriorLabel()->SetProperty("name.image", mitk::StringProperty::New(newSegmentationName)); + + // initialize "showVolume"-property to false to prevent recalculating the volume while working on the segmentation + newSegmentationNode->SetProperty("showVolume", mitk::BoolProperty::New(false)); + + return newSegmentationNode; +} + +mitk::Label::Pointer mitk::LabelSetImageHelper::CreateNewLabel(const LabelSetImage* labelSetImage) +{ + int numberOfLabels = labelSetImage->GetActiveLabelSet()->GetNumberOfLabels(); + + std::string labelName = "New label " + std::to_string(numberOfLabels); + + mitk::LookupTable::Pointer lookupTable = mitk::LookupTable::New(); + lookupTable->SetType(mitk::LookupTable::LookupTableType::MULTILABEL); + double rgb[3]; + lookupTable->GetColor(numberOfLabels, rgb); + mitk::Color labelColor; + labelColor.Set(static_cast(rgb[0]), static_cast(rgb[1]), static_cast(rgb[2])); + + mitk::Label::Pointer newLabel = mitk::Label::New(); + newLabel->SetName(labelName); + newLabel->SetColor(labelColor); + + return newLabel; +} diff --git a/Modules/Multilabel/mitkLabelSetImageHelper.h b/Modules/Multilabel/mitkLabelSetImageHelper.h new file mode 100644 index 0000000000..44c6fc4187 --- /dev/null +++ b/Modules/Multilabel/mitkLabelSetImageHelper.h @@ -0,0 +1,60 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef MITKLABELSETIMAGEHELPER_H +#define MITKLABELSETIMAGEHELPER_H + +#include + +#include +#include + +namespace mitk +{ + /** + * + */ + namespace LabelSetImageHelper + { + /** + * @brief This function creates and returns a new data node containing the given image as data. + * The segmentation node is named according to the given reference data node. + * Some properties are set to automatically link the segmentation node with its parent node. + * + * @param referenceNode The reference node from which the name of the new segmentation node + * is derived. + * @param initialSegmentationImage The segmentation image that is used to initialize the label set image. + * @param segmentationName An optional name for the new segmentation node. + * + * @return The new segmentation node as a data node pointer. + */ + MITKMULTILABEL_EXPORT mitk::DataNode::Pointer CreateNewSegmentationNode(const DataNode* referenceNode, + const Image* initialSegmentationImage = nullptr, const std::string& segmentationName = std::string()); + + /** + * @brief This function creates and returns a new label. The label is automatically assigned a + * label name, depending on the current number of labels of the active label set of the + * given label set image. + * The color of the label is derived from the MULTILABEL lookup table, depending on the + * number of labels. + * + * @param labelSetImage The label set image from which the number of labels of the active label + * set is derived. + * + * @return The new labe as a pointer. + */ + MITKMULTILABEL_EXPORT mitk::Label::Pointer CreateNewLabel(const LabelSetImage* labelSetImage); + + } // namespace LabelSetImageHelper +} // namespace mitk + +#endif // MITKLABELSETIMAGEHELPER_H diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelSegmentationAction.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelSegmentationAction.cpp index d476aa0b44..f993c5e3fa 100644 --- a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelSegmentationAction.cpp +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelSegmentationAction.cpp @@ -1,120 +1,100 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ + #include "QmitkCreateMultiLabelSegmentationAction.h" #include "mitkLabelSetImage.h" -#include "mitkRenderingManager.h" +#include "mitkLabelSetImageHelper.h" -#include "QInputDialog" #include "QMessageBox" -#include "QmitkNewSegmentationDialog.h" -#include "QmitkMultiLabelSegmentationView.h" -#include "QmitkSegmentationOrganNamesHandling.cpp" -//needed for qApp -#include - QmitkCreateMultiLabelSegmentationAction::QmitkCreateMultiLabelSegmentationAction() { } QmitkCreateMultiLabelSegmentationAction::~QmitkCreateMultiLabelSegmentationAction() { } -void QmitkCreateMultiLabelSegmentationAction::Run( const QList &selectedNodes ) +void QmitkCreateMultiLabelSegmentationAction::Run(const QList& selectedNodes) { if (m_DataStorage.IsNull()) { auto message = tr("Data storage not set."); MITK_ERROR << message; - QMessageBox::warning(nullptr, "New Segmentation Session", message); + QMessageBox::warning(nullptr, "New segmentation", message); return; } for ( const auto &referenceNode : selectedNodes ) { - if (referenceNode.IsNotNull()) + if (referenceNode.IsNull()) { - mitk::Image* referenceImage = dynamic_cast( referenceNode->GetData() ); - if (nullptr == referenceImage) - { - MITK_WARN << "Could not create multi label segmentation for non-image node - skipping action."; - continue; - } - - QString newName = QString::fromStdString(referenceNode->GetName()); - newName.append("-labels"); - - bool ok = false; - newName = QInputDialog::getText(nullptr, "New Segmentation Session", "New name:", QLineEdit::Normal, newName, &ok); - if(!ok) return; - - mitk::LabelSetImage::Pointer workingImage = mitk::LabelSetImage::New(); - - try - { - workingImage->Initialize(referenceImage); - } - catch ( mitk::Exception& e ) - { - MITK_ERROR << "Exception caught: " << e.GetDescription(); - QMessageBox::warning(nullptr, "New Segmentation Session", "Could not create a new segmentation session."); - return; - } - - mitk::DataNode::Pointer workingNode = mitk::DataNode::New(); - workingNode->SetData(workingImage); - workingNode->SetName(newName.toStdString()); - - // set additional image information - workingImage->GetExteriorLabel()->SetProperty("name.parent",mitk::StringProperty::New(referenceNode->GetName().c_str())); - workingImage->GetExteriorLabel()->SetProperty("name.image",mitk::StringProperty::New(newName.toStdString().c_str())); - - if (!m_DataStorage->Exists(workingNode)) - m_DataStorage->Add(workingNode, referenceNode); + continue; + } - QmitkNewSegmentationDialog* dialog = new QmitkNewSegmentationDialog( ); - dialog->SetSuggestionList( mitk::OrganNamesHandling::GetDefaultOrganColorString()); - dialog->setWindowTitle("New Label"); + mitk::Image* referenceImage = dynamic_cast(referenceNode->GetData()); + if (nullptr == referenceImage) + { + MITK_WARN << "Could not create multi label segmentation for non-image node."; + continue; + } - int dialogReturnValue = dialog->exec(); + mitk::DataNode::Pointer newSegmentationNode; + try + { + newSegmentationNode = + mitk::LabelSetImageHelper::CreateNewSegmentationNode(referenceNode, referenceImage); + } + catch (mitk::Exception& e) + { + MITK_ERROR << "Exception caught: " << e.GetDescription(); + QMessageBox::warning(nullptr, "New segmentation", "Could not create a new segmentation."); + return; + } - if ( dialogReturnValue == QDialog::Rejected ) return; + auto newLabelSetImage = dynamic_cast(newSegmentationNode->GetData()); + if (nullptr == newLabelSetImage) + { + // something went wrong + return; + } - QString segName = dialog->GetSegmentationName(); - if(segName.isEmpty()) segName = "Unnamed"; - workingImage->GetActiveLabelSet()->AddLabel(segName.toStdString(), dialog->GetColor()); + mitk::Label::Pointer newLabel = mitk::LabelSetImageHelper::CreateNewLabel(newLabelSetImage); + newLabelSetImage->GetActiveLabelSet()->AddLabel(newLabel); + if (!m_DataStorage->Exists(newSegmentationNode)) + { + m_DataStorage->Add(newSegmentationNode, referenceNode); } } } void QmitkCreateMultiLabelSegmentationAction::SetDataStorage(mitk::DataStorage* dataStorage) { m_DataStorage = dataStorage; } void QmitkCreateMultiLabelSegmentationAction::SetFunctionality(berry::QtViewPart*) { //not needed } void QmitkCreateMultiLabelSegmentationAction::SetSmoothed(bool) { //not needed } void QmitkCreateMultiLabelSegmentationAction::SetDecimated(bool) { //not needed } diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/Common/QmitkLabelsWidget.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/Common/QmitkLabelsWidget.cpp index bd9e0955e5..3345f642f1 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/Common/QmitkLabelsWidget.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/Common/QmitkLabelsWidget.cpp @@ -1,183 +1,173 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkLabelsWidget.h" #include // mitk #include #include #include +#include #include // Qmitk #include #include #include "../QmitkSaveMultiLabelPresetAction.h" #include "../QmitkLoadMultiLabelPresetAction.h" // Qt #include QmitkLabelsWidget::QmitkLabelsWidget(QWidget *parent) : QWidget(parent) , m_Controls(new Ui::QmitkLabelsWidgetControls) , m_ToolManager(nullptr) { m_Controls->setupUi(this); m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); m_Controls->savePresetButton->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/actions/document-save.svg"))); m_Controls->loadPresetButton->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/actions/document-open.svg"))); connect(m_Controls->newLabelButton, &QToolButton::clicked, this, &QmitkLabelsWidget::OnNewLabel); connect(m_Controls->lockExteriorButton, &QToolButton::toggled, this, &QmitkLabelsWidget::OnLockExterior); connect(m_Controls->savePresetButton, &QToolButton::clicked, this, &QmitkLabelsWidget::OnSavePreset); connect(m_Controls->loadPresetButton, &QToolButton::clicked, this, &QmitkLabelsWidget::OnLoadPreset); connect(m_Controls->showLabelTableButton, &QToolButton::toggled, this, &QmitkLabelsWidget::ShowLabelTable); this->UpdateGUI(); } QmitkLabelsWidget::~QmitkLabelsWidget() { delete m_Controls; } void QmitkLabelsWidget::UpdateGUI() { m_Controls->newLabelButton->setEnabled(false); m_Controls->lockExteriorButton->setEnabled(false); m_Controls->lockExteriorButton->setChecked(false); m_Controls->savePresetButton->setEnabled(false); m_Controls->loadPresetButton->setEnabled(false); m_Controls->showLabelTableButton->setEnabled(false); m_Controls->showLabelTableButton->setChecked(false); mitk::LabelSetImage* workingImage = this->GetWorkingImage(); if (nullptr == workingImage) { return; } int activeLayer = workingImage->GetActiveLayer(); m_Controls->lockExteriorButton->setEnabled(true); m_Controls->lockExteriorButton->setChecked(workingImage->GetLabel(0, activeLayer)->GetLocked()); m_Controls->showLabelTableButton->setEnabled(true); m_Controls->showLabelTableButton->setChecked(true); m_Controls->newLabelButton->setEnabled(true); m_Controls->savePresetButton->setEnabled(true); m_Controls->loadPresetButton->setEnabled(true); } mitk::LabelSetImage* QmitkLabelsWidget::GetWorkingImage() { mitk::DataNode* workingNode = this->GetWorkingNode(); if (nullptr == workingNode) { return nullptr; } auto workingImage = dynamic_cast(workingNode->GetData()); return workingImage; } mitk::DataNode* QmitkLabelsWidget::GetWorkingNode() { mitk::DataNode* referenceNode = m_ToolManager->GetWorkingData(0); return referenceNode; } void QmitkLabelsWidget::OnNewLabel() { m_ToolManager->ActivateTool(-1); mitk::DataNode* workingNode = this->GetWorkingNode(); if (nullptr == workingNode) { return; } auto workingImage = dynamic_cast(workingNode->GetData()); if (nullptr == workingImage) { return; } - - int numberOfLabels = workingImage->GetActiveLabelSet()->GetNumberOfLabels(); - - mitk::LookupTable::Pointer lookupTable = mitk::LookupTable::New(); - lookupTable->SetType(mitk::LookupTable::LookupTableType::MULTILABEL); - double rgb[3]; - lookupTable->GetColor(numberOfLabels, rgb); - mitk::Color labelColor; - labelColor.Set(static_cast(rgb[0]), static_cast(rgb[1]), static_cast(rgb[2])); - - std::string labelName = "New label " + std::to_string(numberOfLabels); - this->WaitCursorOn(); - workingImage->GetActiveLabelSet()->AddLabel(labelName, labelColor); + mitk::Label::Pointer newLabel = mitk::LabelSetImageHelper::CreateNewLabel(workingImage); + workingImage->GetActiveLabelSet()->AddLabel(newLabel); this->WaitCursorOff(); this->UpdateGUI(); emit LabelsChanged(); } void QmitkLabelsWidget::OnLockExterior(bool checked) { auto workingImage = this->GetWorkingImage(); if (nullptr == workingImage) { return; } workingImage->GetLabel(0)->SetLocked(checked); } void QmitkLabelsWidget::OnSavePreset() { auto workingNode = this->GetWorkingNode(); QmitkAbstractNodeSelectionWidget::NodeList nodes; nodes.append(workingNode); QmitkSaveMultiLabelPresetAction action; action.Run(nodes); } void QmitkLabelsWidget::OnLoadPreset() { auto workingNode = this->GetWorkingNode(); QmitkAbstractNodeSelectionWidget::NodeList nodes; nodes.append(workingNode); QmitkLoadMultiLabelPresetAction action; action.Run(nodes); } void QmitkLabelsWidget::WaitCursorOn() { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); } void QmitkLabelsWidget::WaitCursorOff() { this->RestoreOverrideCursor(); } void QmitkLabelsWidget::RestoreOverrideCursor() { QApplication::restoreOverrideCursor(); } diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp index 392e2bd378..4069b0d819 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp @@ -1,934 +1,908 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkSegmentationView.h" #include "mitkPluginActivator.h" // blueberry #include // mitk #include #include #include #include +#include #include #include #include #include #include #include #include // Qmitk -#include #include #include // us #include #include // Qt #include #include const std::string QmitkSegmentationView::VIEW_ID = "org.mitk.views.segmentation"; QmitkSegmentationView::QmitkSegmentationView() : m_Parent(nullptr) , m_Controls(nullptr) , m_RenderWindowPart(nullptr) , m_ToolManager(nullptr) , m_ReferenceNode(nullptr) , m_WorkingNode(nullptr) , m_AutoSelectionEnabled(false) , m_MouseCursorSet(false) { auto isImage = mitk::TNodePredicateDataType::New(); auto isDwi = mitk::NodePredicateDataType::New("DiffusionImage"); auto isDti = mitk::NodePredicateDataType::New("TensorImage"); auto isOdf = mitk::NodePredicateDataType::New("OdfImage"); auto isSegment = mitk::NodePredicateDataType::New("Segment"); auto validImages = mitk::NodePredicateOr::New(); validImages->AddPredicate(mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isSegment))); validImages->AddPredicate(isDwi); validImages->AddPredicate(isDti); validImages->AddPredicate(isOdf); auto isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); auto isMask = mitk::NodePredicateAnd::New(isBinary, isImage); auto validSegmentations = mitk::NodePredicateOr::New(); validSegmentations->AddPredicate(mitk::TNodePredicateDataType::New()); validSegmentations->AddPredicate(isMask); m_SegmentationPredicate = mitk::NodePredicateAnd::New(); m_SegmentationPredicate->AddPredicate(validSegmentations); m_SegmentationPredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))); m_SegmentationPredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("hidden object"))); m_ReferencePredicate = mitk::NodePredicateAnd::New(); m_ReferencePredicate->AddPredicate(validImages); m_ReferencePredicate->AddPredicate(mitk::NodePredicateNot::New(m_SegmentationPredicate)); m_ReferencePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))); m_ReferencePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("hidden object"))); } QmitkSegmentationView::~QmitkSegmentationView() { if (nullptr != m_Controls) { OnLooseLabelSetConnection(); // deactivate all tools m_ToolManager->ActivateTool(-1); // removing all observers for (NodeTagMapType::iterator dataIter = m_WorkingDataObserverTags.begin(); dataIter != m_WorkingDataObserverTags.end(); ++dataIter) { (*dataIter).first->GetProperty("visible")->RemoveObserver((*dataIter).second); } m_WorkingDataObserverTags.clear(); mitk::RenderingManager::GetInstance()->RemoveObserver(m_RenderingManagerObserverTag); ctkPluginContext* context = mitk::PluginActivator::getContext(); ctkServiceReference ppmRef = context->getServiceReference(); mitk::PlanePositionManagerService* service = context->getService(ppmRef); service->RemoveAllPlanePositions(); context->ungetService(ppmRef); m_ToolManager->SetReferenceData(nullptr); m_ToolManager->SetWorkingData(nullptr); } delete m_Controls; } /**********************************************************************/ /* private Q_SLOTS */ /**********************************************************************/ void QmitkSegmentationView::OnReferenceSelectionChanged(QList nodes) { m_ToolManager->ActivateTool(-1); if (nodes.empty()) { m_Controls->workingNodeSelector->SetNodePredicate(m_SegmentationPredicate); m_ReferenceNode = nullptr; m_ToolManager->SetReferenceData(m_ReferenceNode); this->UpdateGUI(); return; } m_ReferenceNode = nodes.first(); m_ToolManager->SetReferenceData(m_ReferenceNode); if (m_ReferenceNode.IsNotNull()) { // set a predicate such that a segmentation fits the selected reference image geometry auto segPredicate = mitk::NodePredicateAnd::New(m_SegmentationPredicate.GetPointer(), mitk::NodePredicateSubGeometry::New(m_ReferenceNode->GetData()->GetGeometry())); m_Controls->workingNodeSelector->SetNodePredicate(segPredicate); if (m_AutoSelectionEnabled) { // hide all image nodes to later show only the automatically selected ones mitk::DataStorage::SetOfObjects::ConstPointer imageNodes = this->GetDataStorage()->GetSubset(m_ReferencePredicate); for (mitk::DataStorage::SetOfObjects::const_iterator iter = imageNodes->begin(); iter != imageNodes->end(); ++iter) { (*iter)->SetVisibility(false); } } m_ReferenceNode->SetVisibility(true); } this->UpdateGUI(); } void QmitkSegmentationView::OnSegmentationSelectionChanged(QList nodes) { m_ToolManager->ActivateTool(-1); // Remove observer if one was registered auto finding = m_WorkingDataObserverTags.find(m_WorkingNode); if (finding != m_WorkingDataObserverTags.end()) { m_WorkingNode->GetProperty("visible")->RemoveObserver(m_WorkingDataObserverTags[m_WorkingNode]); m_WorkingDataObserverTags.erase(m_WorkingNode); } if (nodes.empty()) { m_WorkingNode = nullptr; m_ToolManager->SetWorkingData(m_WorkingNode); this->UpdateGUI(); return; } if (m_ReferenceNode.IsNull()) { this->UpdateGUI(); return; } mitk::Image::ConstPointer referenceImage = dynamic_cast(m_ReferenceNode->GetData()); if (referenceImage.IsNull()) { this->UpdateGUI(); return; } m_WorkingNode = nodes.first(); m_ToolManager->SetWorkingData(m_WorkingNode); if (m_WorkingNode.IsNotNull()) { if (m_AutoSelectionEnabled) { // hide all segmentation nodes to later show only the automatically selected ones mitk::DataStorage::SetOfObjects::ConstPointer segmentationNodes = this->GetDataStorage()->GetSubset(m_SegmentationPredicate); for (mitk::DataStorage::SetOfObjects::const_iterator iter = segmentationNodes->begin(); iter != segmentationNodes->end(); ++iter) { (*iter)->SetVisibility(false); } } m_WorkingNode->SetVisibility(true); this->OnEstablishLabelSetConnection(); m_Controls->labelSetWidget->ResetAllTableWidgetItems(); auto command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSegmentationView::ValidateSelectionInput); m_WorkingDataObserverTags.insert(std::pair(m_WorkingNode, m_WorkingNode->GetProperty("visible")->AddObserver(itk::ModifiedEvent(), command))); this->InitializeRenderWindows(referenceImage->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, false); } this->UpdateGUI(); } void QmitkSegmentationView::OnNewSegmentation() { m_ToolManager->ActivateTool(-1); - mitk::DataNode::Pointer referenceNode = m_ToolManager->GetReferenceData(0); - if (referenceNode.IsNull()) + if (m_ReferenceNode.IsNull()) { MITK_ERROR << "'Create new segmentation' button should never be clickable unless a reference image is selected."; return; } - mitk::Image::ConstPointer referenceImage = dynamic_cast(referenceNode->GetData()); + mitk::Image::ConstPointer referenceImage = dynamic_cast(m_ReferenceNode->GetData()); if (referenceImage.IsNull()) { QMessageBox::information( m_Parent, "New segmentation", "Please load and select an image before starting some action."); return; } if (referenceImage->GetDimension() <= 1) { QMessageBox::information( m_Parent, "New segmentation", "Segmentation is currently not supported for 2D images"); return; } const auto currentTimePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); unsigned int imageTimeStep = 0; if (referenceImage->GetTimeGeometry()->IsValidTimePoint(currentTimePoint)) { imageTimeStep = referenceImage->GetTimeGeometry()->TimePointToTimeStep(currentTimePoint); } auto segTemplateImage = referenceImage; if (referenceImage->GetDimension() > 3) { auto result = QMessageBox::question(m_Parent, tr("Create a static or dynamic segmentation?"), tr("The selected image has multiple time steps.\n\nDo you want to create a static " "segmentation that is identical for all time steps or do you want to create a " "dynamic segmentation to segment individual time steps?"), tr("Create static segmentation"), tr("Create dynamic segmentation"), QString(), 0, 0); if (result == 0) { auto selector = mitk::ImageTimeSelector::New(); selector->SetInput(referenceImage); selector->SetTimeNr(0); selector->Update(); const auto refTimeGeometry = referenceImage->GetTimeGeometry(); auto newTimeGeometry = mitk::ProportionalTimeGeometry::New(); newTimeGeometry->SetFirstTimePoint(refTimeGeometry->GetMinimumTimePoint()); newTimeGeometry->SetStepDuration(refTimeGeometry->GetMaximumTimePoint() - refTimeGeometry->GetMinimumTimePoint()); mitk::Image::Pointer newImage = selector->GetOutput(); newTimeGeometry->SetTimeStepGeometry(referenceImage->GetGeometry(imageTimeStep), 0); newImage->SetTimeGeometry(newTimeGeometry); segTemplateImage = newImage; } } - QString newName = QString::fromStdString(referenceNode->GetName()); - newName.append("-labels"); - - // ask about the name and organ type of the new segmentation - auto dialog = new QmitkNewSegmentationDialog(m_Parent); - QStringList organColors = mitk::OrganNamesHandling::GetDefaultOrganColorString(); - dialog->SetSuggestionList(organColors); - dialog->SetSegmentationName(newName); - - int dialogReturnValue = dialog->exec(); - if (dialogReturnValue == QDialog::Rejected) + mitk::DataNode::Pointer newSegmentationNode; + try { - return; + this->WaitCursorOn(); + newSegmentationNode = mitk::LabelSetImageHelper::CreateNewSegmentationNode(m_ReferenceNode, segTemplateImage); + this->WaitCursorOff(); } - - std::string newNodeName = dialog->GetSegmentationName().toStdString(); - if (newNodeName.empty()) + catch (mitk::Exception& e) { - newNodeName = "Unnamed"; + this->WaitCursorOff(); + MITK_ERROR << "Exception caught: " << e.GetDescription(); + QMessageBox::warning(m_Parent, "New segmentation", "Could not create a new segmentation."); + return; } - // create a new image of the same dimensions and smallest possible pixel type - auto firstTool = m_ToolManager->GetToolById(0); - if (nullptr == firstTool) + auto newLabelSetImage = dynamic_cast(newSegmentationNode->GetData()); + if (nullptr == newLabelSetImage) { + // something went wrong return; } - mitk::DataNode::Pointer emptySegmentation = nullptr; - try - { - emptySegmentation = firstTool->CreateEmptySegmentationNode(segTemplateImage, newNodeName, dialog->GetColor()); - } - catch (const std::bad_alloc &) - { - QMessageBox::warning(m_Parent, tr("New segmentation"), tr("Could not allocate memory for new segmentation")); - } + mitk::Label::Pointer newLabel = mitk::LabelSetImageHelper::CreateNewLabel(newLabelSetImage); + newLabelSetImage->GetActiveLabelSet()->AddLabel(newLabel); - if (nullptr == emptySegmentation) + if (!this->GetDataStorage()->Exists(newSegmentationNode)) { - return; // could have been aborted by user + this->GetDataStorage()->Add(newSegmentationNode, m_ReferenceNode); } - // initialize "showVolume"-property to false to prevent recalculating the volume while working on the segmentation - emptySegmentation->SetProperty("showVolume", mitk::BoolProperty::New(false)); - - mitk::OrganNamesHandling::UpdateOrganList(organColors, dialog->GetSegmentationName(), dialog->GetColor()); - - // escape ';' here (replace by '\;') - QString stringForStorage = organColors.replaceInStrings(";", "\\;").join(";"); - MITK_DEBUG << "Will store: " << stringForStorage; - this->GetPreferences()->Put("Organ-Color-List", stringForStorage); - this->GetPreferences()->Flush(); - - this->GetDataStorage()->Add(emptySegmentation, referenceNode); - if (m_ToolManager->GetWorkingData(0)) { m_ToolManager->GetWorkingData(0)->SetSelected(false); } - emptySegmentation->SetSelected(true); - m_Controls->workingNodeSelector->SetCurrentSelectedNode(emptySegmentation); + + newSegmentationNode->SetSelected(true); + m_Controls->workingNodeSelector->SetCurrentSelectedNode(newSegmentationNode); } void QmitkSegmentationView::OnManualTool2DSelected(int id) { this->ResetMouseCursor(); mitk::StatusBar::GetInstance()->DisplayText(""); if (id >= 0) { std::string text = "Active Tool: \""; text += m_ToolManager->GetToolById(id)->GetName(); text += "\""; mitk::StatusBar::GetInstance()->DisplayText(text.c_str()); us::ModuleResource resource = m_ToolManager->GetToolById(id)->GetCursorIconResource(); this->SetMouseCursor(resource, 0, 0); } } void QmitkSegmentationView::OnShowMarkerNodes(bool state) { mitk::SegTool2D::Pointer manualSegmentationTool; unsigned int numberOfExistingTools = m_ToolManager->GetTools().size(); for (unsigned int i = 0; i < numberOfExistingTools; i++) { manualSegmentationTool = dynamic_cast(m_ToolManager->GetToolById(i)); if (nullptr == manualSegmentationTool) { continue; } manualSegmentationTool->SetShowMarkerNodes(state); } } void QmitkSegmentationView::OnLayersChanged() { m_Controls->labelSetWidget->ResetAllTableWidgetItems(); } void QmitkSegmentationView::OnLabelsChanged() { m_Controls->labelSetWidget->ResetAllTableWidgetItems(); } void QmitkSegmentationView::OnShowLabelTable(bool value) { m_Controls->labelSetWidget->setVisible(value); } void QmitkSegmentationView::OnGoToLabel(const mitk::Point3D& pos) { if (m_RenderWindowPart) { m_RenderWindowPart->SetSelectedPosition(pos); } } void QmitkSegmentationView::OnResetView() { if (m_RenderWindowPart) { m_RenderWindowPart->ForceImmediateUpdate(); } } /**********************************************************************/ /* private */ /**********************************************************************/ void QmitkSegmentationView::CreateQtPartControl(QWidget* parent) { m_Parent = parent; m_Controls = new Ui::QmitkSegmentationViewControls; m_Controls->setupUi(parent); // *------------------------ // * DATA SELECTION WIDGETS // *------------------------ m_Controls->referenceNodeSelector->SetDataStorage(GetDataStorage()); m_Controls->referenceNodeSelector->SetNodePredicate(m_ReferencePredicate); m_Controls->referenceNodeSelector->SetInvalidInfo("Select an image"); m_Controls->referenceNodeSelector->SetPopUpTitel("Select an image"); m_Controls->referenceNodeSelector->SetPopUpHint("Select an image that should be used to define the geometry and bounds of the segmentation."); m_Controls->workingNodeSelector->SetDataStorage(GetDataStorage()); m_Controls->workingNodeSelector->SetNodePredicate(m_SegmentationPredicate); m_Controls->workingNodeSelector->SetInvalidInfo("Select a segmentation"); m_Controls->workingNodeSelector->SetPopUpTitel("Select a segmentation"); m_Controls->workingNodeSelector->SetPopUpHint("Select a segmentation that should be modified. Only segmentation with the same geometry and within the bounds of the reference image are selected."); connect(m_Controls->referenceNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkSegmentationView::OnReferenceSelectionChanged); connect(m_Controls->workingNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkSegmentationView::OnSegmentationSelectionChanged); // *------------------------ // * TOOLMANAGER // *------------------------ m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); m_ToolManager->SetDataStorage(*(this->GetDataStorage())); m_ToolManager->InitializeTools(); QString segTools2D = tr("Add Subtract Fill Erase Paint Wipe 'Region Growing' 'Live Wire' '2D Fast Marching'"); QString segTools3D = tr("Threshold 'UL Threshold' Otsu 'Fast Marching 3D' 'Region Growing 3D' Watershed Picking"); #ifdef __linux__ segTools3D.append(" nnUNet"); // plugin not enabled for MacOS / Windows #endif std::regex extSegTool2DRegEx("SegTool2D$"); std::regex extSegTool3DRegEx("SegTool3D$"); auto tools = m_ToolManager->GetTools(); for (const auto &tool : tools) { if (std::regex_search(tool->GetNameOfClass(), extSegTool2DRegEx)) { segTools2D.append(QString(" '%1'").arg(tool->GetName())); } else if (std::regex_search(tool->GetNameOfClass(), extSegTool3DRegEx)) { segTools3D.append(QString(" '%1'").arg(tool->GetName())); } } // setup 2D tools m_Controls->toolSelectionBox2D->SetToolManager(*m_ToolManager); m_Controls->toolSelectionBox2D->SetGenerateAccelerators(true); m_Controls->toolSelectionBox2D->SetToolGUIArea(m_Controls->toolGUIArea2D); m_Controls->toolSelectionBox2D->SetDisplayedToolGroups(segTools2D.toStdString()); m_Controls->toolSelectionBox2D->SetLayoutColumns(3); m_Controls->toolSelectionBox2D->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible); connect(m_Controls->toolSelectionBox2D, &QmitkToolSelectionBox::ToolSelected, this, &QmitkSegmentationView::OnManualTool2DSelected); // setup 3D Tools m_Controls->toolSelectionBox3D->SetToolManager(*m_ToolManager); m_Controls->toolSelectionBox3D->SetGenerateAccelerators(true); m_Controls->toolSelectionBox3D->SetToolGUIArea(m_Controls->toolGUIArea3D); m_Controls->toolSelectionBox3D->SetDisplayedToolGroups(segTools3D.toStdString()); m_Controls->toolSelectionBox3D->SetLayoutColumns(3); m_Controls->toolSelectionBox3D->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible); // create general signal / slot connections connect(m_Controls->newSegmentationButton, &QToolButton::clicked, this, &QmitkSegmentationView::OnNewSegmentation); connect(m_Controls->slicesInterpolator, &QmitkSlicesInterpolator::SignalShowMarkerNodes, this, &QmitkSegmentationView::OnShowMarkerNodes); connect(m_Controls->layersWidget, &QmitkLayersWidget::LayersChanged, this, &QmitkSegmentationView::OnLayersChanged); connect(m_Controls->labelsWidget, &QmitkLabelsWidget::LabelsChanged, this, &QmitkSegmentationView::OnLabelsChanged); connect(m_Controls->labelsWidget, &QmitkLabelsWidget::ShowLabelTable, this, &QmitkSegmentationView::OnShowLabelTable); // *------------------------ // * LABELSETWIDGET // *------------------------ connect(m_Controls->labelSetWidget, &QmitkLabelSetWidget::goToLabel, this, &QmitkSegmentationView::OnGoToLabel); connect(m_Controls->labelSetWidget, &QmitkLabelSetWidget::resetView, this, &QmitkSegmentationView::OnResetView); m_Controls->labelSetWidget->SetDataStorage(this->GetDataStorage()); m_Controls->labelSetWidget->SetOrganColors(mitk::OrganNamesHandling::GetDefaultOrganColorString()); m_Controls->labelSetWidget->hide(); auto command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSegmentationView::ValidateSelectionInput); m_RenderingManagerObserverTag = mitk::RenderingManager::GetInstance()->AddObserver(mitk::RenderingManagerViewsInitializedEvent(), command); m_RenderWindowPart = this->GetRenderWindowPart(); if (nullptr != m_RenderWindowPart) { this->RenderWindowPartActivated(m_RenderWindowPart); } // Make sure the GUI notices if appropriate data is already present on creation. // Should be done last, if everything else is configured because it triggers the autoselection of data. m_Controls->referenceNodeSelector->SetAutoSelectNewNodes(true); m_Controls->workingNodeSelector->SetAutoSelectNewNodes(true); this->UpdateGUI(); } void QmitkSegmentationView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) { if (m_RenderWindowPart != renderWindowPart) { m_RenderWindowPart = renderWindowPart; } if (nullptr != m_Parent) { m_Parent->setEnabled(true); } // tell the interpolation about tool manager, data storage and render window part if (nullptr != m_Controls && nullptr != m_RenderWindowPart) { m_Controls->slicesInterpolator->SetDataStorage(this->GetDataStorage()); QList controllers; controllers.push_back(m_RenderWindowPart->GetQmitkRenderWindow("axial")->GetSliceNavigationController()); controllers.push_back(m_RenderWindowPart->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()); controllers.push_back(m_RenderWindowPart->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()); m_Controls->slicesInterpolator->Initialize(m_ToolManager, controllers); } } void QmitkSegmentationView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* /*renderWindowPart*/) { m_RenderWindowPart = nullptr; if (nullptr != m_Parent) { m_Parent->setEnabled(false); } } void QmitkSegmentationView::OnPreferencesChanged(const berry::IBerryPreferences* prefs) { if (nullptr != m_Controls) { bool slimView = prefs->GetBool("slim view", false); m_Controls->toolSelectionBox2D->SetShowNames(!slimView); m_Controls->toolSelectionBox3D->SetShowNames(!slimView); } m_AutoSelectionEnabled = prefs->GetBool("auto selection", false); this->ApplyDisplayOptions(); } void QmitkSegmentationView::NodeAdded(const mitk::DataNode* node) { if (m_SegmentationPredicate->CheckNode(node)) { this->ApplyDisplayOptions(const_cast(node)); } } void QmitkSegmentationView::NodeRemoved(const mitk::DataNode* node) { if (!m_SegmentationPredicate->CheckNode(node)) { return; } // remove all possible contour markers of the segmentation mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = this->GetDataStorage()->GetDerivations( node, mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true))); ctkPluginContext* context = mitk::PluginActivator::getContext(); ctkServiceReference ppmRef = context->getServiceReference(); mitk::PlanePositionManagerService* service = context->getService(ppmRef); for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it) { std::string nodeName = node->GetName(); unsigned int t = nodeName.find_last_of(" "); unsigned int id = atof(nodeName.substr(t + 1).c_str()) - 1; service->RemovePlanePosition(id); this->GetDataStorage()->Remove(it->Value()); } context->ungetService(ppmRef); service = nullptr; mitk::Image* image = dynamic_cast(node->GetData()); mitk::SurfaceInterpolationController::GetInstance()->RemoveInterpolationSession(image); } void QmitkSegmentationView::OnEstablishLabelSetConnection() { if (m_WorkingNode.IsNull()) { return; } auto workingImage = dynamic_cast(m_WorkingNode->GetData()); if (nullptr == workingImage) { return; } workingImage->GetActiveLabelSet()->AddLabelEvent += mitk::MessageDelegate( m_Controls->labelSetWidget, &QmitkLabelSetWidget::ResetAllTableWidgetItems); workingImage->GetActiveLabelSet()->RemoveLabelEvent += mitk::MessageDelegate( m_Controls->labelSetWidget, &QmitkLabelSetWidget::ResetAllTableWidgetItems); workingImage->GetActiveLabelSet()->ModifyLabelEvent += mitk::MessageDelegate( m_Controls->labelSetWidget, &QmitkLabelSetWidget::UpdateAllTableWidgetItems); workingImage->GetActiveLabelSet()->AllLabelsModifiedEvent += mitk::MessageDelegate( m_Controls->labelSetWidget, &QmitkLabelSetWidget::UpdateAllTableWidgetItems); workingImage->GetActiveLabelSet()->ActiveLabelEvent += mitk::MessageDelegate1(m_Controls->labelSetWidget, &QmitkLabelSetWidget::SelectLabelByPixelValue); // Removed in T27851 to have a chance to react to AfterChangeLayerEvent. Did it brake something? // workingImage->BeforeChangeLayerEvent += mitk::MessageDelegate( // this, &QmitkMultiLabelSegmentationView::OnLooseLabelSetConnection); workingImage->AfterChangeLayerEvent += mitk::MessageDelegate( this, &QmitkSegmentationView::UpdateGUI); } void QmitkSegmentationView::OnLooseLabelSetConnection() { if (m_WorkingNode.IsNull()) { return; } auto workingImage = dynamic_cast(m_WorkingNode->GetData()); if (nullptr == workingImage) { return; } // Reset LabelSetWidget Events workingImage->GetActiveLabelSet()->AddLabelEvent -= mitk::MessageDelegate( m_Controls->labelSetWidget, &QmitkLabelSetWidget::ResetAllTableWidgetItems); workingImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate( m_Controls->labelSetWidget, &QmitkLabelSetWidget::ResetAllTableWidgetItems); workingImage->GetActiveLabelSet()->ModifyLabelEvent -= mitk::MessageDelegate( m_Controls->labelSetWidget, &QmitkLabelSetWidget::UpdateAllTableWidgetItems); workingImage->GetActiveLabelSet()->AllLabelsModifiedEvent -= mitk::MessageDelegate( m_Controls->labelSetWidget, &QmitkLabelSetWidget::UpdateAllTableWidgetItems); workingImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1(m_Controls->labelSetWidget, &QmitkLabelSetWidget::SelectLabelByPixelValue); // Removed in T27851 to have a chance to react to AfterChangeLayerEvent. Did it brake something? // workingImage->BeforeChangeLayerEvent -= mitk::MessageDelegate( // this, &QmitkMultiLabelSegmentationView::OnLooseLabelSetConnection); workingImage->AfterChangeLayerEvent -= mitk::MessageDelegate( this, &QmitkSegmentationView::UpdateGUI); } void QmitkSegmentationView::ApplyDisplayOptions() { if (nullptr == m_Parent) { return; } if (nullptr == m_Controls) { return; // might happen on initialization (preferences loaded) } mitk::DataStorage::SetOfObjects::ConstPointer allImages = this->GetDataStorage()->GetSubset(m_SegmentationPredicate); for (mitk::DataStorage::SetOfObjects::const_iterator iter = allImages->begin(); iter != allImages->end(); ++iter) { this->ApplyDisplayOptions(*iter); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSegmentationView::ApplyDisplayOptions(mitk::DataNode* node) { if (nullptr == node) { return; } auto drawOutline = mitk::BoolProperty::New(GetPreferences()->GetBool("draw outline", true)); auto labelSetImage = dynamic_cast(node->GetData()); if (nullptr != labelSetImage) { // node is a multi label segmentation, // its outline property can be set in the segmentation preference page node->SetProperty("labelset.contour.active", drawOutline); // force render window update to show outline node->GetData()->Modified(); } else if (nullptr != node->GetData()) { // node is a legacy binary segmentation bool isBinary = false; node->GetBoolProperty("binary", isBinary); if (isBinary) { node->SetProperty("outline binary", drawOutline); node->SetProperty("outline width", mitk::FloatProperty::New(2.0)); // force render window update to show outline node->GetData()->Modified(); } } } void QmitkSegmentationView::OnContourMarkerSelected(const mitk::DataNode* node) { QmitkRenderWindow* selectedRenderWindow = nullptr; auto* renderWindowPart = this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN); auto* axialRenderWindow = renderWindowPart->GetQmitkRenderWindow("axial"); auto* sagittalRenderWindow = renderWindowPart->GetQmitkRenderWindow("sagittal"); auto* coronalRenderWindow = renderWindowPart->GetQmitkRenderWindow("coronal"); auto* threeDRenderWindow = renderWindowPart->GetQmitkRenderWindow("3d"); bool PlanarFigureInitializedWindow = false; // find initialized renderwindow if (node->GetBoolProperty("PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, axialRenderWindow->GetRenderer())) { selectedRenderWindow = axialRenderWindow; } if (!selectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, sagittalRenderWindow->GetRenderer())) { selectedRenderWindow = sagittalRenderWindow; } if (!selectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, coronalRenderWindow->GetRenderer())) { selectedRenderWindow = coronalRenderWindow; } if (!selectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, threeDRenderWindow->GetRenderer())) { selectedRenderWindow = threeDRenderWindow; } // make node visible if (nullptr != selectedRenderWindow) { std::string nodeName = node->GetName(); unsigned int t = nodeName.find_last_of(" "); unsigned int id = atof(nodeName.substr(t + 1).c_str()) - 1; ctkPluginContext* context = mitk::PluginActivator::getContext(); ctkServiceReference ppmRef = context->getServiceReference(); mitk::PlanePositionManagerService* service = context->getService(ppmRef); selectedRenderWindow->GetSliceNavigationController()->ExecuteOperation(service->GetPlanePosition(id)); context->ungetService(ppmRef); selectedRenderWindow->GetRenderer()->GetCameraController()->Fit(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSegmentationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes) { if (0 == nodes.size()) { return; } std::string markerName = "Position"; unsigned int numberOfNodes = nodes.size(); std::string nodeName = nodes.at(0)->GetName(); if ((numberOfNodes == 1) && (nodeName.find(markerName) == 0)) { this->OnContourMarkerSelected(nodes.at(0)); return; } } void QmitkSegmentationView::ResetMouseCursor() { if (m_MouseCursorSet) { mitk::ApplicationCursor::GetInstance()->PopCursor(); m_MouseCursorSet = false; } } void QmitkSegmentationView::SetMouseCursor(const us::ModuleResource& resource, int hotspotX, int hotspotY) { // Remove previously set mouse cursor if (m_MouseCursorSet) { this->ResetMouseCursor(); } if (resource) { us::ModuleResourceStream cursor(resource, std::ios::binary); mitk::ApplicationCursor::GetInstance()->PushCursor(cursor, hotspotX, hotspotY); m_MouseCursorSet = true; } } void QmitkSegmentationView::UpdateGUI() { mitk::DataNode* referenceNode = m_ToolManager->GetReferenceData(0); bool hasReferenceNode = referenceNode != nullptr; mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); bool hasWorkingNode = workingNode != nullptr; m_Controls->newSegmentationButton->setEnabled(false); m_Controls->slicesInterpolator->setEnabled(false); if (hasReferenceNode) { m_Controls->newSegmentationButton->setEnabled(true); } if (hasWorkingNode && hasReferenceNode) { m_Controls->slicesInterpolator->setEnabled(true); int layer = -1; referenceNode->GetIntProperty("layer", layer); workingNode->SetIntProperty("layer", layer + 1); } m_Controls->layersWidget->UpdateGUI(); m_Controls->labelsWidget->UpdateGUI(); this->ValidateSelectionInput(); } void QmitkSegmentationView::ValidateSelectionInput() { this->UpdateWarningLabel(""); m_Controls->labelSetWidget->setEnabled(false); // the argument is actually not used // enable status depends on the tool manager selection m_Controls->toolSelectionBox2D->setEnabled(false); m_Controls->toolSelectionBox3D->setEnabled(false); mitk::DataNode* referenceNode = m_Controls->referenceNodeSelector->GetSelectedNode(); mitk::DataNode* workingNode = m_Controls->workingNodeSelector->GetSelectedNode(); if (nullptr == referenceNode) { return; } if (nullptr == workingNode) { return; } mitk::IRenderWindowPart* renderWindowPart = this->GetRenderWindowPart(); auto workingNodeIsVisible = renderWindowPart && workingNode->IsVisible(renderWindowPart->GetQmitkRenderWindow("axial")->GetRenderer()); if (!workingNodeIsVisible) { this->UpdateWarningLabel(tr("The selected segmentation is currently not visible!")); return; } /* * Here we check whether the geometry of the selected segmentation image is aligned with the worldgeometry. * At the moment it is not supported to use a geometry different from the selected image for reslicing. * For further information see Bug 16063 */ const mitk::BaseGeometry* workingNodeGeo = workingNode->GetData()->GetGeometry(); const mitk::BaseGeometry* worldGeo = renderWindowPart->GetQmitkRenderWindow("3d")->GetSliceNavigationController()->GetCurrentGeometry3D(); if (nullptr != workingNodeGeo && nullptr != worldGeo) { if (mitk::Equal(*workingNodeGeo->GetBoundingBox(), *worldGeo->GetBoundingBox(), mitk::eps, true)) { m_ToolManager->SetReferenceData(referenceNode); m_ToolManager->SetWorkingData(workingNode); m_Controls->labelSetWidget->setEnabled(true); m_Controls->toolSelectionBox2D->setEnabled(true); m_Controls->toolSelectionBox3D->setEnabled(true); return; } } m_ToolManager->SetReferenceData(referenceNode); m_ToolManager->SetWorkingData(nullptr); this->UpdateWarningLabel(tr("Please perform a reinit on the segmentation image!")); } void QmitkSegmentationView::UpdateWarningLabel(QString text) { if (text.size() == 0) { m_Controls->selectionWarningLabel->hide(); } else { m_Controls->selectionWarningLabel->show(); m_Controls->selectionWarningLabel->setText("" + text + ""); } }