diff --git a/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.cpp b/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.cpp new file mode 100644 index 0000000000..b10910a7cb --- /dev/null +++ b/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.cpp @@ -0,0 +1,151 @@ +/*============================================================================ + +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.s + +============================================================================*/ + +#include "QmitkSetupVirtualEnvUtil.h" +#include +#include +#include +#include +#include "mitkLogMacros.h" + +QmitkSetupVirtualEnvUtil::QmitkSetupVirtualEnvUtil() +{ + m_BaseDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QDir::separator() + + qApp->organizationName() + QDir::separator(); +} + +QmitkSetupVirtualEnvUtil::QmitkSetupVirtualEnvUtil(const QString baseDir) +{ + m_BaseDir = baseDir; +} + +QString QmitkSetupVirtualEnvUtil::GetBaseDir() +{ + return m_BaseDir; +} + +QString QmitkSetupVirtualEnvUtil::GetVirtualEnvPath() +{ + return m_venvPath; +} + +std::map QmitkSetupVirtualEnvUtil::GetInstallParameters( + QmitkSetupVirtualEnvUtil::Tool packageName) +{ + std::map parameters; + + switch (packageName) + { + case QmitkSetupVirtualEnvUtil::Tool::TOTALSEGMENTATOR: + { + parameters["venv_name"] = ".totalsegmentator"; + parameters["pkg_version"] = "1.5.2"; + parameters["pkg_names"] = "Totalsegmentator==1.5.2,scikit-image"; + break; + } + default: + { + std::runtime_error("Unsupported Tool type"); + break; + } + } + return parameters; +} + +bool QmitkSetupVirtualEnvUtil::SetupVirtualEnv(QmitkSetupVirtualEnvUtil::Tool packageName) +{ + std::vector packages; + std::map params = GetInstallParameters(packageName); + + std::stringstream pkgs(params["pkg_names"]); + while (pkgs.good()) + { + std::string pkg; + std::getline(pkgs, pkg, ','); + packages.push_back(pkg); + } + + QString venvName = QString::fromStdString(params["venv_name"]); + QDir folderPath(m_BaseDir); + folderPath.mkdir(venvName); + if (!folderPath.cd(venvName)) + { + return false; // Check if directory creation was successful. + } + mitk::ProcessExecutor::ArgumentListType args; + auto spExec = mitk::ProcessExecutor::New(); + auto spCommand = itk::CStyleCommand::New(); + spCommand->SetCallback([](itk::Object * /*pCaller*/, const itk::EventObject &e, void *) + { + std::string testCOUT; + std::string testCERR; + const auto *pEvent = dynamic_cast(&e); + if (pEvent) + { + testCOUT += pEvent->GetOutput(); + MITK_INFO << testCOUT; + } + const auto *pErrEvent = dynamic_cast(&e); + if (pErrEvent) + { + testCERR += pErrEvent->GetOutput(); + MITK_ERROR << testCERR; + } + }); + spExec->AddObserver(mitk::ExternalProcessOutputEvent(), spCommand); + + args.push_back("-m"); + args.push_back("venv"); + args.push_back(venvName.toStdString()); + spExec->Execute(m_BaseDir.toStdString(), "/usr/bin/python3", args); // Setup local virtual environment + + if (folderPath.cd("bin")) + { + m_venvPath = folderPath.absolutePath(); + std::string workingDir = m_venvPath.toStdString(); + for (auto& package : packages) + { + PipInstall(package, workingDir); + } + std::string pythonCode; // python syntax to check if torch is installed with CUDA. + pythonCode.append("import torch;"); + pythonCode.append("print('Pytorch installed with CUDA') if torch.cuda.is_available else ValueError('PyTorch " + "installed without CUDA');"); + ExecutePython(pythonCode, workingDir); + return true; + } + return false; +} + +void QmitkSetupVirtualEnvUtil::PipInstall(const std::string &library, const std::string &workingDir) +{ + mitk::ProcessExecutor::ArgumentListType args; + auto spExec = mitk::ProcessExecutor::New(); + auto spCommand = itk::CStyleCommand::New(); + //spCommand->SetCallback(tool->onPythonProcessEvent); + spExec->AddObserver(mitk::ExternalProcessOutputEvent(), spCommand); + args.push_back("install"); + args.push_back(library); + spExec->Execute(workingDir, "pip3", args); // Install TotalSegmentator in it. +} + +void QmitkSetupVirtualEnvUtil::ExecutePython(const std::string &pythonCode, const std::string &workingDir) +{ + mitk::ProcessExecutor::ArgumentListType args; + auto spExec = mitk::ProcessExecutor::New(); + auto spCommand = itk::CStyleCommand::New(); + // spCommand->SetCallback(tool->onPythonProcessEvent); + spExec->AddObserver(mitk::ExternalProcessOutputEvent(), spCommand); + args.push_back("-c"); + args.push_back(pythonCode); + spExec->Execute(workingDir, "python3", args); +} diff --git a/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.h b/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.h new file mode 100644 index 0000000000..70eeb79ba3 --- /dev/null +++ b/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.h @@ -0,0 +1,47 @@ +/*============================================================================ + +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.s + +============================================================================*/ + +#ifndef QmitkSetupVirtualEnvUtil_h_Included +#define QmitkSetupVirtualEnvUtil_h_Included + +#include "mitkProcessExecutor.h" +#include +#include +#include "mitkLogMacros.h" + +/** + * @brief Class to ... + */ +class MITKSEGMENTATIONUI_EXPORT QmitkSetupVirtualEnvUtil +{ +public: + enum Tool + { + TOTALSEGMENTATOR + }; + + QmitkSetupVirtualEnvUtil(const QString baseDir); + QmitkSetupVirtualEnvUtil(); + + bool SetupVirtualEnv(Tool packageName = Tool::TOTALSEGMENTATOR); + void PipInstall(const std::string &library, const std::string &workingDir); + void ExecutePython(const std::string &args, const std::string &pythonPath); + std::map GetInstallParameters(QmitkSetupVirtualEnvUtil::Tool); + QString GetBaseDir(); + QString GetVirtualEnvPath(); + +private: + QString m_BaseDir; + QString m_venvPath; +}; + +#endif \ No newline at end of file diff --git a/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.cpp index 3d87a8eb51..d5bc19d088 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.cpp @@ -1,418 +1,422 @@ #include "QmitkTotalSegmentatorToolGUI.h" #include "mitkProcessExecutor.h" #include "mitkTotalSegmentatorTool.h" #include #include #include #include #include #include #include #include #include MITK_TOOL_GUI_MACRO(MITKSEGMENTATIONUI_EXPORT, QmitkTotalSegmentatorToolGUI, "") QmitkTotalSegmentatorToolGUI::QmitkTotalSegmentatorToolGUI() : QmitkMultiLabelSegWithPreviewToolGUIBase(), m_SuperclassEnableConfirmSegBtnFnc(m_EnableConfirmSegBtnFnc) { // Nvidia-smi command returning zero doesn't always imply lack of GPUs. // Pytorch uses its own libraries to communicate to the GPUs. Hence, only a warning can be given. if (m_GpuLoader.GetGPUCount() == 0) { std::string warning = "WARNING: No GPUs were detected on your machine. The TotalSegmentator tool can be very slow."; this->ShowErrorMessage(warning); } m_EnableConfirmSegBtnFnc = [this](bool enabled) { return !m_FirstPreviewComputation ? m_SuperclassEnableConfirmSegBtnFnc(enabled) : false; }; } void QmitkTotalSegmentatorToolGUI::ConnectNewTool(mitk::SegWithPreviewTool *newTool) { Superclass::ConnectNewTool(newTool); newTool->IsTimePointChangeAwareOff(); m_FirstPreviewComputation = true; } void QmitkTotalSegmentatorToolGUI::InitializeUI(QBoxLayout *mainLayout) { m_Controls.setupUi(this); m_Controls.pythonEnvComboBox->addItem("Select"); m_Controls.pythonEnvComboBox->setDuplicatesEnabled(false); m_Controls.previewButton->setDisabled(true); m_Controls.statusLabel->setTextFormat(Qt::RichText); m_Controls.subtaskComboBox->addItems(m_VALID_TASKS); this->AutoParsePythonPaths(); this->SetGPUInfo(); if (m_GpuLoader.GetGPUCount() != 0) { WriteStatusMessage(QString("STATUS: Welcome to Total Segmentator tool. You're in luck: " + QString::number(m_GpuLoader.GetGPUCount()) + " GPU(s) were detected.")); } else { WriteErrorMessage(QString("STATUS: Welcome to Total Segmentator tool. Sorry, " + QString::number(m_GpuLoader.GetGPUCount()) + " GPUs were detected.")); } mainLayout->addLayout(m_Controls.verticalLayout); connect(m_Controls.previewButton, SIGNAL(clicked()), this, SLOT(OnPreviewBtnClicked())); connect(m_Controls.installButton, SIGNAL(clicked()), this, SLOT(OnInstallBtnClicked())); // connect(m_Controls.pythonEnvComboBox, // SIGNAL(currentTextChanged(const QString &)), // this, // SLOT(OnPythonPathChanged(const QString &))); Superclass::InitializeUI(mainLayout); QString lastSelectedPyEnv = m_Settings.value("TotalSeg/LastPythonPath").toString(); m_Controls.pythonEnvComboBox->insertItem(0, lastSelectedPyEnv); const QString storageDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QDir::separator() + qApp->organizationName() + QDir::separator() + m_VENV_NAME; m_IsInstalled = this->IsTotalSegmentatorInstalled(storageDir); if (m_IsInstalled) { OnPythonPathChanged(storageDir); this->EnableAll(m_IsInstalled); } } void QmitkTotalSegmentatorToolGUI::EnableWidgets(bool enabled) { Superclass::EnableWidgets(enabled); } void QmitkTotalSegmentatorToolGUI::SetGPUInfo() { std::vector specs = m_GpuLoader.GetAllGPUSpecs(); for (const QmitkGPUSpec &gpuSpec : specs) { m_Controls.gpuComboBox->addItem(QString::number(gpuSpec.id) + ": " + gpuSpec.name + " (" + gpuSpec.memory + ")"); } if (specs.empty()) { m_Controls.gpuComboBox->setEditable(true); m_Controls.gpuComboBox->addItem(QString::number(0)); m_Controls.gpuComboBox->setValidator(new QIntValidator(0, 999, this)); } } unsigned int QmitkTotalSegmentatorToolGUI::FetchSelectedGPUFromUI() { QString gpuInfo = m_Controls.gpuComboBox->currentText(); if (m_GpuLoader.GetGPUCount() == 0) { return static_cast(gpuInfo.toInt()); } else { QString gpuId = gpuInfo.split(":", QString::SplitBehavior::SkipEmptyParts).first(); return static_cast(gpuId.toInt()); } } //namespace //{ // void onPythonProcessEvent(itk::Object * /*pCaller*/, const itk::EventObject &e, void *) // { // std::string testCOUT; // std::string testCERR; // const auto *pEvent = dynamic_cast(&e); // // if (pEvent) // { // testCOUT = testCOUT + pEvent->GetOutput(); // MITK_INFO << testCOUT; // } // // const auto *pErrEvent = dynamic_cast(&e); // // if (pErrEvent) // { // testCERR = testCERR + pErrEvent->GetOutput(); // MITK_ERROR << testCERR; // } // } //} // namespace void QmitkTotalSegmentatorToolGUI::EnableAll(bool isEnable) { m_Controls.previewButton->setEnabled(isEnable); m_Controls.subtaskComboBox->setEnabled(isEnable); m_Controls.installButton->setEnabled((!isEnable)); } void QmitkTotalSegmentatorToolGUI::OnInstallBtnClicked() { - const QString storageDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QDir::separator() + - qApp->organizationName() + QDir::separator(); - MITK_INFO << storageDir.toStdString(); + //const QString storageDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QDir::separator() + + // qApp->organizationName() + QDir::separator(); + //MITK_INFO << storageDir.toStdString(); bool isInstalled = false; #ifndef _WIN32 - isInstalled = SetUpTotalSegmentator(storageDir); + //isInstalled = SetUpTotalSegmentator(storageDir); + isInstalled = m_Installer.SetupVirtualEnv(); #endif if (isInstalled) { - const QString pythonPath = storageDir + m_VENV_NAME; + // const QString pythonPath = storageDir + m_VENV_NAME; + const QString pythonPath = m_Installer.GetVirtualEnvPath(); + MITK_INFO << pythonPath.toStdString(); OnPythonPathChanged(pythonPath); this->WriteStatusMessage("Successfully installed TotalSegmentator"); } else { this->WriteErrorMessage("Couldn't find TotalSegmentator"); } this->EnableAll(isInstalled); } + bool QmitkTotalSegmentatorToolGUI::SetUpTotalSegmentatorWIN(const QString & /*path*/) { return false; } bool QmitkTotalSegmentatorToolGUI::SetUpTotalSegmentator(const QString &path) { auto tool = this->GetConnectedToolAs(); if (nullptr == tool) { return false; } bool isInstalled = false; QDir folderPath(path); if (this->IsTotalSegmentatorInstalled(folderPath.absoluteFilePath(m_VENV_NAME))) { return true; } folderPath.mkdir(m_VENV_NAME); if (!folderPath.cd(m_VENV_NAME)) { return false; // Check if directory creation was successful. } mitk::ProcessExecutor::ArgumentListType args; auto spExec = mitk::ProcessExecutor::New(); auto spCommand = itk::CStyleCommand::New(); spCommand->SetCallback(tool->onPythonProcessEvent); spExec->AddObserver(mitk::ExternalProcessOutputEvent(), spCommand); args.push_back("-m"); args.push_back("venv"); args.push_back(m_VENV_NAME.toStdString()); spExec->Execute(path.toStdString(), "/usr/bin/python3", args);// Setup local virtual environment if (folderPath.cd("bin")) { std::string workingDir; workingDir = folderPath.absolutePath().toStdString(); args.clear(); args.push_back("install"); args.push_back("Totalsegmentator==" + m_TOTALSEGMENTATOR_VERSION); spExec->Execute(workingDir, "pip3", args); // Install TotalSegmentator in it. args.clear(); args.push_back("install"); args.push_back("scikit-image"); spExec->Execute(workingDir, "pip3", args); // Install TotalSegmentator in it. if (this->IsTotalSegmentatorInstalled(folderPath.absolutePath())) { isInstalled = true; // Check if installation was successful } args.clear(); args.push_back("-c"); std::string pythonCode; // python syntax to check if torch is installed with CUDA. pythonCode.append("import torch;"); pythonCode.append("print('Pytorch installed with CUDA') if torch.cuda.is_available else ValueError('PyTorch installed without CUDA');"); args.push_back(pythonCode); spExec->Execute(workingDir, "python3", args); } return isInstalled; } void QmitkTotalSegmentatorToolGUI::OnPreviewBtnClicked() { auto tool = this->GetConnectedToolAs(); if (nullptr == tool) { return; } QString pythonPathTextItem = ""; try { m_Controls.previewButton->setEnabled(false); qApp->processEvents(); if (!this->IsTotalSegmentatorInstalled(m_PythonPath)) { throw std::runtime_error(m_WARNING_TOTALSEG_NOT_FOUND); } //pythonPathTextItem = m_Controls.pythonEnvComboBox->currentText(); bool isFast = m_Controls.fastBox->isChecked(); QString subTask = m_Controls.subtaskComboBox->currentText(); if (subTask != m_VALID_TASKS[0]) { isFast = true; } tool->SetPythonPath(m_PythonPath.toStdString()); tool->SetGpuId(FetchSelectedGPUFromUI()); tool->SetFast(isFast); tool->SetSubTask(subTask.toStdString()); this->WriteStatusMessage(QString("STATUS: Starting Segmentation task... This might take a while.")); tool->UpdatePreview(); m_Controls.previewButton->setEnabled(true); } catch (const std::exception &e) { std::stringstream errorMsg; errorMsg << "STATUS: 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; } this->SetLabelSetPreview(tool->GetPreviewSegmentation()); tool->IsTimePointChangeAwareOn(); this->ActualizePreviewLabelVisibility(); this->WriteStatusMessage("STATUS: Segmentation task finished successfully."); if (!pythonPathTextItem.isEmpty())// only cache if the prediction ended without errors. { QString lastSelectedPyEnv = m_Settings.value("TotalSeg/LastPythonPath").toString(); if (lastSelectedPyEnv != pythonPathTextItem) { m_Settings.setValue("TotalSeg/LastPythonPath", pythonPathTextItem); } } } void QmitkTotalSegmentatorToolGUI::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; } void QmitkTotalSegmentatorToolGUI::WriteStatusMessage(const QString &message) { m_Controls.statusLabel->setText(message); m_Controls.statusLabel->setStyleSheet("font-weight: bold; color: white"); } void QmitkTotalSegmentatorToolGUI::WriteErrorMessage(const QString &message) { m_Controls.statusLabel->setText(message); m_Controls.statusLabel->setStyleSheet("font-weight: bold; color: red"); } bool QmitkTotalSegmentatorToolGUI::IsTotalSegmentatorInstalled(const QString &pythonPath) { QString fullPath = pythonPath; #ifdef _WIN32 if (!(fullPath.endsWith("Scripts", Qt::CaseInsensitive) || fullPath.endsWith("Scripts/", Qt::CaseInsensitive))) { fullPath += QDir::separator() + QString("Scripts"); } #else if (!(fullPath.endsWith("bin", Qt::CaseInsensitive) || fullPath.endsWith("bin/", Qt::CaseInsensitive))) { fullPath += QDir::separator() + QString("bin"); } #endif fullPath = fullPath.mid(fullPath.indexOf(" ") + 1); bool isExists = QFile::exists(fullPath + QDir::separator() + QString("TotalSegmentator")) && #ifdef _WIN32 QFile::exists(fullPath + QDir::separator() + QString("python.exe")); #else QFile::exists(fullPath + QDir::separator() + QString("python3")); #endif return isExists; } void QmitkTotalSegmentatorToolGUI::AutoParsePythonPaths() { QString homeDir = QDir::homePath(); std::vector searchDirs; #ifdef _WIN32 searchDirs.push_back(QString("C:") + QDir::separator() + QString("ProgramData") + QDir::separator() + QString("anaconda3")); #else // Add search locations for possible standard python paths here searchDirs.push_back(homeDir + QDir::separator() + "environments"); searchDirs.push_back(homeDir + QDir::separator() + "anaconda3"); searchDirs.push_back(homeDir + QDir::separator() + "miniconda3"); searchDirs.push_back(homeDir + QDir::separator() + "opt" + QDir::separator() + "miniconda3"); searchDirs.push_back(homeDir + QDir::separator() + "opt" + QDir::separator() + "anaconda3"); #endif for (QString searchDir : searchDirs) { if (searchDir.endsWith("anaconda3", Qt::CaseInsensitive)) { if (QDir(searchDir).exists()) { m_Controls.pythonEnvComboBox->insertItem(0, "(base): " + searchDir); searchDir.append((QDir::separator() + QString("envs"))); } } for (QDirIterator subIt(searchDir, QDir::AllDirs, QDirIterator::NoIteratorFlags); subIt.hasNext();) { subIt.next(); QString envName = subIt.fileName(); if (!envName.startsWith('.')) // Filter out irrelevent hidden folders, if any. { m_Controls.pythonEnvComboBox->insertItem(0, "(" + envName + "): " + subIt.filePath()); } } } m_Controls.pythonEnvComboBox->setCurrentIndex(-1); } void QmitkTotalSegmentatorToolGUI::OnPythonPathChanged(const QString &pyEnv) { if (pyEnv == QString("Select")) { QString path = QFileDialog::getExistingDirectory(m_Controls.pythonEnvComboBox->parentWidget(), "Python Path", "dir"); if (!path.isEmpty()) { this->OnPythonPathChanged(path); // recall same function for new path validation bool oldState = m_Controls.pythonEnvComboBox->blockSignals(true); // block signal firing while inserting item m_Controls.pythonEnvComboBox->insertItem(0, path); m_Controls.pythonEnvComboBox->setCurrentIndex(0); m_Controls.pythonEnvComboBox->blockSignals( oldState); // unblock signal firing after inserting item. Remove this after Qt6 migration } } else if (!this->IsTotalSegmentatorInstalled(pyEnv)) { this->ShowErrorMessage(m_WARNING_TOTALSEG_NOT_FOUND); m_Controls.previewButton->setDisabled(true); } else { // Show positive status meeage m_Controls.previewButton->setDisabled(false); m_PythonPath = pyEnv.mid(pyEnv.indexOf(" ") + 1); #ifdef _WIN32 if (!(m_PythonPath.endsWith("Scripts", Qt::CaseInsensitive) || m_PythonPath.endsWith("Scripts/", Qt::CaseInsensitive))) { m_PythonPath += QDir::separator() + QString("Scripts"); } #else if (!(m_PythonPath.endsWith("bin", Qt::CaseInsensitive) || m_PythonPath.endsWith("bin/", Qt::CaseInsensitive))) { m_PythonPath += QDir::separator() + QString("bin"); } #endif } } diff --git a/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.h b/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.h index 389fdadf5c..1a4ba1e2e8 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.h +++ b/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.h @@ -1,116 +1,118 @@ #ifndef QmitkTotalSegmentatorToolGUI_h_Included #define QmitkTotalSegmentatorToolGUI_h_Included #include "QmitkMultiLabelSegWithPreviewToolGUIBase.h" #include "ui_QmitkTotalSegmentatorGUIControls.h" #include #include #include "QmitknnUNetGPU.h" #include +#include "QmitkSetupVirtualEnvUtil.h" class MITKSEGMENTATIONUI_EXPORT QmitkTotalSegmentatorToolGUI : public QmitkMultiLabelSegWithPreviewToolGUIBase { Q_OBJECT public: mitkClassMacro(QmitkTotalSegmentatorToolGUI, QmitkMultiLabelSegWithPreviewToolGUIBase); itkFactorylessNewMacro(Self); itkCloneMacro(Self); protected slots : /** * @brief Qt Slot */ void OnPreviewBtnClicked(); /** * @brief Qt Slot */ void OnPythonPathChanged(const QString &); /** @brief Qt Slot */ void OnInstallBtnClicked(); protected: QmitkTotalSegmentatorToolGUI(); ~QmitkTotalSegmentatorToolGUI() = default; void ConnectNewTool(mitk::SegWithPreviewTool* newTool) override; void InitializeUI(QBoxLayout* mainLayout) override; void EnableWidgets(bool enabled) override; /** @brief Enable (or Disable) GUI elements. */ void EnableAll(bool); /** * @brief Searches and parses paths of python virtual enviroments * from predefined lookout locations */ void AutoParsePythonPaths(); /** * @brief Checks if TotalSegmentator command is valid in the selected python virtual environment. * * @return bool */ bool IsTotalSegmentatorInstalled(const QString &); /** * @brief Creates a QMessage object and shows on screen. */ void ShowErrorMessage(const std::string &, QMessageBox::Icon = QMessageBox::Critical); /** * @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 Adds GPU information to the gpu combo box. * In case, there aren't any GPUs avaialble, the combo box will be * rendered editable. */ void SetGPUInfo(); /** * @brief Returns GPU id of the selected GPU from the Combo box. * * @return unsigned int */ unsigned int FetchSelectedGPUFromUI(); bool SetUpTotalSegmentator(const QString &); bool SetUpTotalSegmentatorWIN(const QString &); /** * @brief For storing values like Python path across sessions. */ QSettings m_Settings; QString m_PythonPath; + QmitkSetupVirtualEnvUtil m_Installer; QmitkGPULoader m_GpuLoader; Ui_QmitkTotalSegmentatorToolGUIControls m_Controls; bool m_FirstPreviewComputation = true; bool m_IsInstalled = false; EnableConfirmSegBtnFunctionType m_SuperclassEnableConfirmSegBtnFnc; const std::string m_WARNING_TOTALSEG_NOT_FOUND = "TotalSegmentator is not detected in the selected python environment.Please select a valid " "python environment or install TotalSegmentator."; const QStringList m_VALID_TASKS = {"total", "cerebral_bleed", "hip_implant", "coronary_arteries"}; const QString m_VENV_NAME = ".totalsegmentator"; const std::string m_TOTALSEGMENTATOR_VERSION = "1.5.2"; }; #endif diff --git a/Modules/SegmentationUI/files.cmake b/Modules/SegmentationUI/files.cmake index 60a3005397..4c712cc2b8 100644 --- a/Modules/SegmentationUI/files.cmake +++ b/Modules/SegmentationUI/files.cmake @@ -1,105 +1,107 @@ set(CPP_FILES Qmitk/QmitkSegWithPreviewToolGUIBase.cpp Qmitk/QmitkMultiLabelSegWithPreviewToolGUIBase.cpp Qmitk/QmitkBinaryThresholdToolGUIBase.cpp Qmitk/QmitkBinaryThresholdToolGUI.cpp Qmitk/QmitkBinaryThresholdULToolGUI.cpp Qmitk/QmitkConfirmSegmentationDialog.cpp Qmitk/QmitkCopyToClipBoardDialog.cpp Qmitk/QmitkDrawPaintbrushToolGUI.cpp Qmitk/QmitkErasePaintbrushToolGUI.cpp Qmitk/QmitkEditableContourToolGUIBase.cpp Qmitk/QmitkGrowCutToolGUI.cpp Qmitk/QmitkLiveWireTool2DGUI.cpp Qmitk/QmitkLassoToolGUI.cpp Qmitk/QmitkOtsuTool3DGUI.cpp Qmitk/QmitkPaintbrushToolGUI.cpp Qmitk/QmitkPickingToolGUI.cpp Qmitk/QmitkSlicesInterpolator.cpp Qmitk/QmitkToolGUI.cpp Qmitk/QmitkToolGUIArea.cpp Qmitk/QmitkToolSelectionBox.cpp Qmitk/QmitknnUNetFolderParser.cpp Qmitk/QmitknnUNetToolGUI.cpp Qmitk/QmitknnUNetWorker.cpp Qmitk/QmitknnUNetGPU.cpp Qmitk/QmitkSurfaceStampWidget.cpp Qmitk/QmitkMaskStampWidget.cpp Qmitk/QmitkStaticDynamicSegmentationDialog.cpp Qmitk/QmitkSurfaceBasedInterpolatorWidget.cpp Qmitk/QmitkSimpleLabelSetListWidget.cpp Qmitk/QmitkSegmentationTaskListWidget.cpp Qmitk/QmitkTotalSegmentatorToolGUI.cpp + Qmitk/QmitkSetupVirtualEnvUtil.cpp SegmentationUtilities/QmitkBooleanOperationsWidget.cpp SegmentationUtilities/QmitkContourModelToImageWidget.cpp SegmentationUtilities/QmitkImageMaskingWidget.cpp SegmentationUtilities/QmitkMorphologicalOperationsWidget.cpp SegmentationUtilities/QmitkSurfaceToImageWidget.cpp SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp SegmentationUtilities/QmitkDataSelectionWidget.cpp ) set(MOC_H_FILES Qmitk/QmitkSegWithPreviewToolGUIBase.h Qmitk/QmitkMultiLabelSegWithPreviewToolGUIBase.h Qmitk/QmitkBinaryThresholdToolGUIBase.h Qmitk/QmitkBinaryThresholdToolGUI.h Qmitk/QmitkBinaryThresholdULToolGUI.h Qmitk/QmitkConfirmSegmentationDialog.h Qmitk/QmitkCopyToClipBoardDialog.h Qmitk/QmitkDrawPaintbrushToolGUI.h Qmitk/QmitkErasePaintbrushToolGUI.h Qmitk/QmitkEditableContourToolGUIBase.h Qmitk/QmitkGrowCutToolGUI.h Qmitk/QmitkLiveWireTool2DGUI.h Qmitk/QmitkLassoToolGUI.h Qmitk/QmitkOtsuTool3DGUI.h Qmitk/QmitkPaintbrushToolGUI.h Qmitk/QmitkPickingToolGUI.h Qmitk/QmitkSlicesInterpolator.h Qmitk/QmitkToolGUI.h Qmitk/QmitkToolGUIArea.h Qmitk/QmitkToolSelectionBox.h Qmitk/QmitknnUNetFolderParser.h Qmitk/QmitknnUNetToolGUI.h Qmitk/QmitknnUNetGPU.h Qmitk/QmitknnUNetWorker.h Qmitk/QmitknnUNetEnsembleLayout.h Qmitk/QmitkSurfaceStampWidget.h Qmitk/QmitkMaskStampWidget.h Qmitk/QmitkStaticDynamicSegmentationDialog.h Qmitk/QmitkSurfaceBasedInterpolatorWidget.h Qmitk/QmitkSimpleLabelSetListWidget.h Qmitk/QmitkSegmentationTaskListWidget.h Qmitk/QmitkTotalSegmentatorToolGUI.h + Qmitk/QmitkSetupVirtualEnvUtil.h SegmentationUtilities/QmitkBooleanOperationsWidget.h SegmentationUtilities/QmitkContourModelToImageWidget.h SegmentationUtilities/QmitkImageMaskingWidget.h SegmentationUtilities/QmitkMorphologicalOperationsWidget.h SegmentationUtilities/QmitkSurfaceToImageWidget.h SegmentationUtilities/QmitkSegmentationUtilityWidget.h SegmentationUtilities/QmitkDataSelectionWidget.h ) set(UI_FILES Qmitk/QmitkConfirmSegmentationDialog.ui Qmitk/QmitkGrowCutToolWidgetControls.ui Qmitk/QmitkOtsuToolWidgetControls.ui Qmitk/QmitkSurfaceStampWidgetGUIControls.ui Qmitk/QmitkMaskStampWidgetGUIControls.ui Qmitk/QmitkSurfaceBasedInterpolatorWidgetGUIControls.ui Qmitk/QmitknnUNetToolGUIControls.ui Qmitk/QmitkEditableContourToolGUIControls.ui Qmitk/QmitkSegmentationTaskListWidget.ui Qmitk/QmitkTotalSegmentatorGUIControls.ui SegmentationUtilities/QmitkBooleanOperationsWidgetControls.ui SegmentationUtilities/QmitkContourModelToImageWidgetControls.ui SegmentationUtilities/QmitkImageMaskingWidgetControls.ui SegmentationUtilities/QmitkMorphologicalOperationsWidgetControls.ui SegmentationUtilities/QmitkSurfaceToImageWidgetControls.ui SegmentationUtilities/QmitkDataSelectionWidgetControls.ui ) set(QRC_FILES resources/SegmentationUI.qrc )