diff --git a/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUI.cpp index d94bb81d6f..438c86405b 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUI.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUI.cpp @@ -1,286 +1,277 @@ /*============================================================================ 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 "QmitkMonaiLabelToolGUI.h" #include "mitkMonaiLabelTool.h" #include "usServiceReference.h" #include <QIcon> #include <QUrl> #include <QmitkStyleManager.h> #include <usGetModuleContext.h> #include <usModule.h> #include <usModuleContext.h> #include <QMessageBox> QmitkMonaiLabelToolGUI::QmitkMonaiLabelToolGUI(int dimension) : QmitkMultiLabelSegWithPreviewToolGUIBase(), m_SuperclassEnableConfirmSegBtnFnc(m_EnableConfirmSegBtnFnc) { m_Dimension = dimension; m_EnableConfirmSegBtnFnc = [this](bool enabled) { return !m_FirstPreviewComputation ? m_SuperclassEnableConfirmSegBtnFnc(enabled) : false; }; } QmitkMonaiLabelToolGUI::~QmitkMonaiLabelToolGUI() { auto tool = this->GetConnectedToolAs<mitk::MonaiLabelTool>(); if (nullptr != tool) { tool->MonaiStatusEvent -= mitk::MessageDelegate1<QmitkMonaiLabelToolGUI, const bool>(this, &QmitkMonaiLabelToolGUI::StatusMessageListener); } } void QmitkMonaiLabelToolGUI::ConnectNewTool(mitk::SegWithPreviewTool *newTool) { Superclass::ConnectNewTool(newTool); newTool->IsTimePointChangeAwareOff(); m_FirstPreviewComputation = true; } void QmitkMonaiLabelToolGUI::InitializeUI(QBoxLayout *mainLayout) { m_Controls.setupUi(this); mainLayout->addLayout(m_Controls.verticalLayout); connect(m_Controls.previewButton, SIGNAL(clicked()), this, SLOT(OnPreviewBtnClicked())); connect(m_Controls.fetchUrl, SIGNAL(clicked()), this, SLOT(OnFetchBtnClicked())); connect(m_Controls.modelBox, QOverload<int>::of(&QComboBox::activated), [=](int index) { OnModelChanged(m_Controls.modelBox->itemText(index)); }); - connect(m_Controls.labelBox, SIGNAL(currentTextChanged(const QString&)), this, SLOT(OnLabelChanged(const QString&))); QIcon refreshIcon = QmitkStyleManager::ThemeIcon(QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/actions/view-refresh.svg")); m_Controls.fetchUrl->setIcon(refreshIcon); Superclass::InitializeUI(mainLayout); } void QmitkMonaiLabelToolGUI::EnableWidgets(bool enabled) { Superclass::EnableWidgets(enabled); } void QmitkMonaiLabelToolGUI::StatusMessageListener(const bool status) { if (!status) { return; } /* auto tool = this->GetConnectedToolAs<mitk::MonaiLabelTool>(); if (nullptr == tool) { return; } this->SetLabelSetPreview(tool->GetPreviewSegmentation()); this->ActualizePreviewLabelVisibility();*/ Superclass::DisplayWidgets(false); m_FirstPreviewComputation = false; } void QmitkMonaiLabelToolGUI::DisplayWidgets(bool enabled) { Superclass::DisplayWidgets(enabled); m_Controls.previewButton->setVisible(enabled); } void QmitkMonaiLabelToolGUI::OnModelChanged(const QString &modelName) { auto tool = this->GetConnectedToolAs<mitk::MonaiLabelTool>(); if (nullptr == tool) { return; } - m_Controls.labelBox->clear(); + m_Controls.labelListLabel->clear(); mitk::MonaiModelInfo model = tool->GetModelInfoFromName(modelName.toStdString()); if ("deepgrow" == model.type || "deepedit" == model.type) { this->WriteStatusMessage("Interactive model selected. Please press SHIFT + click on the render windows.\n"); m_Controls.previewButton->setEnabled(false); this->DisplayWidgets(false); } else { this->WriteStatusMessage("Auto-segmentation model selected. Please click on Preview. Label selection will be ignored.\n"); m_Controls.previewButton->setEnabled(true); this->DisplayWidgets(true); } std::string selectedModel = m_Controls.modelBox->currentText().toStdString(); for (const mitk::MonaiModelInfo &modelObject : tool->m_InfoParameters->models) { if (modelObject.name == selectedModel) { auto requestObject = std::make_unique<mitk::MonaiLabelRequest>(); requestObject->model = modelObject; requestObject->hostName = tool->m_InfoParameters->hostName; requestObject->port = tool->m_InfoParameters->port; tool->m_RequestParameters = std::move(requestObject); + QStringList supportedLabels; for (const auto &label : modelObject.labels) { - m_Controls.labelBox->addItem(QString::fromStdString(label.first)); + supportedLabels << QString::fromStdString(label.first); } + m_Controls.labelListLabel->setText(supportedLabels.join(',')); break; } } tool->MonaiStatusEvent += mitk::MessageDelegate1<QmitkMonaiLabelToolGUI, const bool>(this, &QmitkMonaiLabelToolGUI::StatusMessageListener); } -void QmitkMonaiLabelToolGUI::OnLabelChanged(const QString &label) -{ - auto tool = this->GetConnectedToolAs<mitk::MonaiLabelTool>(); - if (nullptr == tool) - { - return; - } - tool->m_RequestParameters->requestLabel = label.toStdString(); -} - void QmitkMonaiLabelToolGUI::OnFetchBtnClicked() { auto tool = this->GetConnectedToolAs<mitk::MonaiLabelTool>(); if (nullptr == tool) { return; } tool->m_InfoParameters.reset(); m_Controls.modelBox->clear(); m_Controls.appBox->clear(); QString urlString = m_Controls.urlBox->text(); QUrl url(urlString); if (url.isValid() && !url.isLocalFile() && !url.hasFragment() && !url.hasQuery()) // sanity check { QString hostName = url.host(); int port = url.port(); try { tool->GetOverallInfo(hostName.toStdString(), port); // tool->GetOverallInfo("localhost",8000"); if (nullptr != tool->m_InfoParameters) { std::string response = tool->m_InfoParameters->name; std::vector<mitk::MonaiModelInfo> autoModels = tool->GetAutoSegmentationModels(m_Dimension); std::vector<mitk::MonaiModelInfo> interactiveModels = tool->GetInteractiveSegmentationModels(m_Dimension); autoModels.insert(autoModels.end(), interactiveModels.begin(), interactiveModels.end()); this->WriteStatusMessage(QString::fromStdString(response)); m_Controls.appBox->addItem(QString::fromStdString(response)); for (auto &model : autoModels) { m_Controls.modelBox->addItem(QString::fromStdString(model.name)); } m_Controls.modelBox->setCurrentIndex(-1); } } catch (const mitk::Exception &e) { MITK_ERROR << e.GetDescription(); // Add GUI msg box to show } } else { MITK_ERROR << "Invalid URL entered: " << urlString.toStdString(); // set as status message on GUI } } void QmitkMonaiLabelToolGUI::OnPreviewBtnClicked() { auto tool = this->GetConnectedToolAs<mitk::MonaiLabelTool>(); if (nullptr == tool) { return; } QMessageBox::StandardButton reply; reply = QMessageBox::question(this, "Confirm", m_CONFIRM_QUESTION_TEXT, QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::No) { MITK_INFO << "Didn't went ahead with Monai Label inferencing"; return; } bool test = false; if (!test) { std::string selectedModel = m_Controls.modelBox->currentText().toStdString(); for (const mitk::MonaiModelInfo &modelObject : tool->m_InfoParameters->models) { if (modelObject.name == selectedModel) { auto requestObject = std::make_unique<mitk::MonaiLabelRequest>(); requestObject->model = modelObject; requestObject->hostName = tool->m_InfoParameters->hostName; requestObject->port = tool->m_InfoParameters->port; if (!m_FirstPreviewComputation && tool->GetIsLastSuccess() && *requestObject == *(tool->m_RequestParameters)) { MITK_INFO << "won't do segmentation..."; return; } else { tool->m_RequestParameters = std::move(requestObject); } break; } } } else { MITK_INFO << " RUNNING ON TEST parameters..."; tool->m_RequestParameters = std::make_unique<mitk::MonaiLabelRequest>(); mitk::MonaiModelInfo modelObject; modelObject.name = "deepedit_seg"; tool->m_RequestParameters->model = modelObject; tool->m_RequestParameters->hostName = "localhost"; tool->m_RequestParameters->port = 8000; } try { tool->UpdatePreview(); } catch (const std::exception &e) { std::stringstream errorMsg; errorMsg << "<b>STATUS: </b>Error while processing parameters for TotalSegmentator segmentation. Reason: " << e.what(); this->ShowErrorMessage(errorMsg.str()); this->WriteErrorMessage(QString::fromStdString(errorMsg.str())); m_Controls.previewButton->setEnabled(true); return; } catch (...) { std::string errorMsg = "Unkown error occured while generation TotalSegmentator segmentation."; this->ShowErrorMessage(errorMsg); m_Controls.previewButton->setEnabled(true); return; } } void QmitkMonaiLabelToolGUI::WriteStatusMessage(const QString &message) { m_Controls.responseNote->setText(message); m_Controls.responseNote->setStyleSheet("font-weight: bold; color: white"); qApp->processEvents(); } void QmitkMonaiLabelToolGUI::WriteErrorMessage(const QString &message) { m_Controls.responseNote->setText(message); m_Controls.responseNote->setStyleSheet("font-weight: bold; color: red"); qApp->processEvents(); } void QmitkMonaiLabelToolGUI::ShowErrorMessage(const std::string &message, QMessageBox::Icon icon) { this->setCursor(Qt::ArrowCursor); QMessageBox *messageBox = new QMessageBox(icon, nullptr, message.c_str()); messageBox->exec(); delete messageBox; MITK_WARN << message; } diff --git a/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUI.h b/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUI.h index 78de10b153..c1f93d252e 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUI.h +++ b/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUI.h @@ -1,76 +1,75 @@ /*============================================================================ 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 QmitkMonaiLabelToolGUI_h_Included #define QmitkMonaiLabelToolGUI_h_Included #include "QmitkMultiLabelSegWithPreviewToolGUIBase.h" #include "ui_QmitkMonaiLabelToolGUIControls.h" #include <MitkSegmentationUIExports.h> #include <QMessageBox> class MITKSEGMENTATIONUI_EXPORT QmitkMonaiLabelToolGUI : public QmitkMultiLabelSegWithPreviewToolGUIBase { Q_OBJECT public: mitkClassMacro(QmitkMonaiLabelToolGUI, QmitkMultiLabelSegWithPreviewToolGUIBase); itkCloneMacro(Self); protected slots : void OnPreviewBtnClicked(); void OnFetchBtnClicked(); void OnModelChanged(const QString&); - void OnLabelChanged(const QString&); protected: QmitkMonaiLabelToolGUI(int); ~QmitkMonaiLabelToolGUI(); void ConnectNewTool(mitk::SegWithPreviewTool* newTool) override; void InitializeUI(QBoxLayout* mainLayout) override; void EnableWidgets(bool enabled) override; virtual void DisplayWidgets(bool enabled); /** * @brief Writes any message in white on the tool pane. */ void WriteStatusMessage(const QString &); /** * @brief Writes any message in red on the tool pane. */ void WriteErrorMessage(const QString &); /** * @brief Creates a QMessage object and shows on screen. */ void ShowErrorMessage(const std::string &, QMessageBox::Icon = QMessageBox::Critical); /** * @brief Function to listen to tool class status emitters. */ void StatusMessageListener(const bool); private: Ui_QmitkMonaiLabelToolGUIControls m_Controls; bool m_FirstPreviewComputation = true; EnableConfirmSegBtnFunctionType m_SuperclassEnableConfirmSegBtnFnc; int m_Dimension; QString m_CONFIRM_QUESTION_TEXT = "Data will be sent to the processing server devoid of any patient information. Are you sure you want continue?"; }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUIControls.ui b/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUIControls.ui index 1c2d040345..483c30a236 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUIControls.ui +++ b/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUIControls.ui @@ -1,196 +1,209 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>QmitkMonaiLabelToolGUIControls</class> <widget class="QWidget" name="QmitkMonaiLabelToolGUIControls"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>699</width> <height>352</height> </rect> </property> <property name="sizePolicy"> <sizepolicy hsizetype="Ignored" vsizetype="Minimum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> <width>100</width> <height>0</height> </size> </property> <property name="maximumSize"> <size> <width>100000</width> <height>100000</height> </size> </property> <property name="windowTitle"> <string>QmitkMonaiToolWidget</string> </property> <layout class="QVBoxLayout" name="verticalLayout"> <property name="spacing"> <number>0</number> </property> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <item> <layout class="QGridLayout" name="basicSettingsLayout"> <item row="1" column="0"> <widget class="QLabel" name="monaiUrlLabel"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="text"> <string>Monai Server URL:</string> </property> </widget> </item> <item row="1" column="1" colspan="3"> <widget class="QLineEdit" name="urlBox"> <property name="text"> <string>http://localhost:8000</string> </property> </widget> </item> <item row="1" column="4"> <widget class="QPushButton" name="fetchUrl"/> </item> <item row="2" column="0"> <widget class="QLabel" name="appLabel"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="text"> <string>Available Apps:</string> </property> </widget> </item> <item row="0" column="0" colspan="4"> <widget class="QLabel" name="welcomeNote"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="text"> - <string><html><head/><body><p>Welcome to MONAI Label App in MITK. [Experimental]</p><p>Please note that this is only an interface to MONAI Label. MITK does not ship with any apps. Make sure to have a started a MONAI Label server beforehand. </p><p>Refer to <a href="https://github.com/MIC-DKFZ/nnUNet"><span style=" text-decoration: underline; color:#0000ff;">https://docs.monai.io/projects/label/en/latest/</span></a> to learn everything about the MONAI Label App.</p><p><br/></p><p>Provide a valid URL (eg. http://localhost:8000) to the server &amp; start the workflow. </p><p><br/></p></body></html></string> + <string><html><head/><body><p>Welcome to MONAI Label App in MITK. [Experimental]</p><p>Please note that this is only an interface to MONAI Label. MITK does not ship with any apps. Make sure to have a started a MONAI Label server beforehand. </p><p>Refer to <a href="https://github.com/MIC-DKFZ/nnUNet"><span style=" text-decoration: underline; color:#0000ff;">https://docs.monai.io/projects/label/en/latest/</span></a> to learn everything about the MONAI Label App.</p><p><br/></p><p>Provide a valid URL (eg. http://localhost:8000) to the server &amp; start the workflow.</p><p><br/></p></body></html></string> </property> <property name="textFormat"> <enum>Qt::RichText</enum> </property> <property name="wordWrap"> <bool>true</bool> </property> </widget> </item> <item row="2" column="1" colspan="3"> <widget class="ctkComboBox" name="appBox"/> </item> - <item row="3" column="0"> - <widget class="QLabel" name="modelLabel"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Models:</string> - </property> - </widget> - </item> + <item row="3" column="0"> + <widget class="QLabel" name="modelLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Models:</string> + </property> + </widget> + </item> <item row="3" column="1" colspan="3"> <widget class="ctkComboBox" name="modelBox"/> </item> - <item row="4" column="0"> - <widget class="QLabel" name="labelSetLabel"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Labels:</string> - </property> - </widget> - </item> - <item row="4" column="1" colspan="3"> - <widget class="ctkComboBox" name="labelBox"/> - </item> + <item row="4" column="0"> + <widget class="QLabel" name="supportedLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Supported Labels:</string> + </property> + </widget> + </item> + <item row="4" column="1" colspan="3"> + <widget class="QLabel" name="labelListLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> </layout> </item> <item> <widget class="QLabel" name="responseNote"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="text"> - <string><html><head/><body><p>Welcome to Monai Label in MITK. [Experimental]</string> + <string><html><head/><body><p>Welcome to Monai Label in MITK. [Experimental]</p></body></html></string> </property> <property name="textFormat"> <enum>Qt::RichText</enum> </property> <property name="wordWrap"> <bool>true</bool> </property> </widget> </item> <item> <widget class="QPushButton" name="previewButton"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="maximumSize"> <size> <width>100000</width> <height>16777215</height> </size> </property> <property name="text"> <string>Preview</string> </property> </widget> </item> </layout> </widget> <layoutdefault spacing="6" margin="11"/> <customwidgets> <customwidget> <class>ctkComboBox</class> <extends>QComboBox</extends> <header location="global">ctkComboBox.h</header> <container>1</container> </customwidget> </customwidgets> <resources/> <connections/> </ui>