diff --git a/Modules/SegmentationUI/Qmitk/QmitknnUNetFolderParser.h b/Modules/SegmentationUI/Qmitk/QmitknnUNetFolderParser.h index 885d0333ee..c8b58854da 100644 --- a/Modules/SegmentationUI/Qmitk/QmitknnUNetFolderParser.h +++ b/Modules/SegmentationUI/Qmitk/QmitknnUNetFolderParser.h @@ -1,179 +1,262 @@ /*============================================================================ 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 QmitknnUNetFolderParser_h_Included #define QmitknnUNetFolderParser_h_Included #include "QmitknnUNetToolGUI.h" #include #include #include struct FolderNode { QString name; QString path; // parent std::vector> subFolders; }; class MITKSEGMENTATIONUI_EXPORT QmitknnUNetFolderParser { public: + + /** + * @brief Construct a new QmitknnUNetFolderParser object + * Initializes root folder node object pointer calls + * @param parentFolder + */ QmitknnUNetFolderParser(const QString parentFolder) { m_RootNode = std::make_shared(); m_RootNode->path = parentFolder; m_RootNode->name = QString("nnUNet"); m_RootNode->subFolders.clear(); - RefreshHierarchy(); + InitDirs(m_RootNode, 0); } - ~QmitknnUNetFolderParser() = default; /*{ DeleteDirs(m_RootNode, LEVEL); }*/ - void RefreshHierarchy() { InitDirs(m_RootNode, 0); } + /** + * @brief Destroy the QmitknnUNetFolderParser object + * + */ + ~QmitknnUNetFolderParser() = default; /*{ DeleteDirs(m_RootNode, LEVEL); }*/ + /** + * @brief Returns the "Results Folder" string which is parent path of the root node. + * + * @return QString + */ QString getResultsFolder() { return m_RootNode->path; } + /** + * @brief Returns the Model Names from root node. Template function, + * type can be any of stl or Qt containers which supports push_back call. + * + * @tparam T + * @return T + */ template T getModelNames() { - QStringList models = GetSubFolderNamesFromNode(m_RootNode); + auto models = GetSubFolderNamesFromNode(m_RootNode); return models; } - + + /** + * @brief Returns the task names for a given model. Template function, + * type can be any of stl or Qt containers which supports push_back call. + * + * @tparam T + * @return T + */ template T getTasksForModel(const QString &modelName) { std::shared_ptr modelNode = GetSubNodeMatchingNameCrietria(modelName, m_RootNode); - QStringList tasks = GetSubFolderNamesFromNode(modelNode); + auto tasks = GetSubFolderNamesFromNode(modelNode); return tasks; } + /** + * @brief Returns the models names for a given task. Template function, + * type can be any of stl or Qt containers which supports push_back call. + * + * @tparam T + * @return T + */ template T getModelsForTask(const QString &taskName) { - QStringList modelsForTask; - QStringList models = GetSubFolderNamesFromNode(m_RootNode); + T modelsForTask; + auto models = GetSubFolderNamesFromNode(m_RootNode); foreach (QString model, models) { QStringList taskList = getTasksForModel(model); if (taskList.contains(taskName, Qt::CaseInsensitive)) { modelsForTask << model; } } return modelsForTask; } + /** + * @brief Returns the trainer / planner names for a given task & model. Template function, + * type can be any of stl or Qt containers which supports push_back call. + * + * @tparam T + * @return T + */ template T getTrainerPlannersForTask(const QString &taskName, const QString &modelName) { - QStringList tps; std::shared_ptr modelNode = GetSubNodeMatchingNameCrietria(modelName, m_RootNode); std::shared_ptr taskNode = GetSubNodeMatchingNameCrietria(taskName, modelNode); - tps = GetSubFolderNamesFromNode(taskNode); + auto tps = GetSubFolderNamesFromNode(taskNode); return tps; } + /** + * @brief Returns the Folds names for a given trainer,planner,task & model name. Template function, + * type can be any of stl or Qt containers which supports push_back call. + * + * @tparam T + * @return T + */ template T getFoldsForTrainerPlanner(const QString &trainer, const QString &planner, const QString &taskName, const QString &modelName) { - QStringList folds; std::shared_ptr modelNode = GetSubNodeMatchingNameCrietria(modelName, m_RootNode); std::shared_ptr taskNode = GetSubNodeMatchingNameCrietria(taskName, modelNode); QString trainerPlanner = trainer + QString("__") + planner; std::shared_ptr tpNode = GetSubNodeMatchingNameCrietria(trainerPlanner, taskNode); - folds = GetSubFolderNamesFromNode(tpNode); + auto folds = GetSubFolderNamesFromNode(tpNode); return folds; } private: - const int LEVEL = 4; + const int m_LEVEL = 4; std::shared_ptr m_RootNode; + /** + * @brief Iterates through the root node and returns the sub FolderNode object Matching Name Crietria + * + * @param queryName + * @param parentNode + * @return std::shared_ptr + */ std::shared_ptr GetSubNodeMatchingNameCrietria(const QString &queryName, std::shared_ptr parentNode) { std::shared_ptr retNode; std::vector> subNodes = parentNode->subFolders; for (std::shared_ptr node : subNodes) { if (node->name == queryName) { retNode = node; break; } } return retNode; } + /** + * @brief Returns the sub folder names for a folder node object. Template function, + * type can be any of stl or Qt containers which supports push_back call. + * + * @tparam T + * @return T + */ template T GetSubFolderNamesFromNode(const std::shared_ptr parent) { T folders; std::vector> subNodes = parent->subFolders; for (std::shared_ptr folder : subNodes) { folders.push_back(folder->name); } return folders; } + /** + * @brief Iterates through the sub folder hierarchy upto a level provided + * and create a tree structure. + * + * @param parent + * @param level + */ void InitDirs(std::shared_ptr parent, int level) { QString searchFolder = parent->path + QDir::separator() + parent->name; auto subFolders = FetchFoldersFromDir(searchFolder); level++; foreach (QString folder, subFolders) { std::shared_ptr fp = std::make_shared(); fp->path = searchFolder; fp->name = folder; - if (level < this->LEVEL) + if (level < this->m_LEVEL) { InitDirs(fp, level); } parent->subFolders.push_back(fp); } } + /** + * @brief Iterates through the sub folder hierarchy upto a level provided + * and clears the sub folder std::vector from each node. + * + * @param parent + * @param level + */ void DeleteDirs(std::shared_ptr parent, int level) { level++; for (std::shared_ptr subFolder : parent->subFolders) { - if (level < LEVEL) + if (level < m_LEVEL) { DeleteDirs(subFolder, level); } parent->subFolders.clear(); } } + /** + * @brief Template function to fetch all folders inside a given path. + * The type can be any of stl or Qt containers which supports push_back call. + * + * @tparam T + * @param path + * @return T + */ template T FetchFoldersFromDir(const QString &path) { T folders; for (QDirIterator it(path, QDir::AllDirs, QDirIterator::NoIteratorFlags); it.hasNext();) { it.next(); if (!it.fileName().startsWith('.')) { folders.push_back(it.fileName()); } } return folders; } }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUI.h b/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUI.h index 56bd782c97..756f8048a5 100644 --- a/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUI.h +++ b/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUI.h @@ -1,230 +1,220 @@ /*============================================================================ 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 QmitknnUNetToolGUI_h_Included #define QmitknnUNetToolGUI_h_Included #include "QmitkAutoMLSegmentationToolGUIBase.h" #include "QmitknnUNetFolderParser.h" #include "QmitknnUNetGPU.h" #include "QmitknnUNetWorker.h" #include "mitknnUnetTool.h" #include "ui_QmitknnUNetToolGUIControls.h" #include #include // #include #include #include class MITKSEGMENTATIONUI_EXPORT QmitknnUNetToolGUI : public QmitkAutoMLSegmentationToolGUIBase { Q_OBJECT public: mitkClassMacro(QmitknnUNetToolGUI, QmitkAutoMLSegmentationToolGUIBase); itkFactorylessNewMacro(Self); itkCloneMacro(Self); protected slots: /** * @brief Qt slot * */ void OnPreviewRequested(); /** * @brief Qt slot * */ void OnDirectoryChanged(const QString &); /** * @brief Qt slot * */ void OnModelChanged(const QString &); /** * @brief Qt slot * */ void OnTaskChanged(const QString &); /** * @brief Qt slot * */ void OnTrainerChanged(const QString &); /** * @brief Qt slot * */ void OnCheckBoxChanged(int); /** * @brief Qthread slot to capture failures from thread worker and * shows error message * */ void SegmentationProcessFailed(); /** * @brief Qthread to capture sucessfull nnUNet segmentation. * Further, renders the LabelSet image */ void SegmentationResultHandler(mitk::nnUNetTool *); /** * @brief Qt Slot * */ void OnModalitiesNumberChanged(int); /** * @brief Qt Slot * */ void OnPythonPathChanged(const QString &); /** * @brief Qt Slot * */ void OnModalPositionChanged(int); signals: /** * @brief signal for starting the segmentation which is caught by a worker thread. */ void Operate(mitk::nnUNetTool *); protected: QmitknnUNetToolGUI(); ~QmitknnUNetToolGUI() = default; void ConnectNewTool(mitk::AutoSegmentationWithPreviewTool *newTool) override; void InitializeUI(QBoxLayout *mainLayout) override; void EnableWidgets(bool enabled) override; private: /** * @brief Parses the ensemble UI elements and sets to nnUNetTool object pointer. * */ void ProcessEnsembleModelsParams(mitk::nnUNetTool::Pointer); /** * @brief Parses the UI elements and sets to nnUNetTool object pointer. * */ void ProcessModelParams(mitk::nnUNetTool::Pointer); /** * @brief Creates and renders QmitknnUNetTaskParamsUITemplate layout for ensemble input. */ void ShowEnsembleLayout(bool visible = true); /** * @brief Creates a QMessage object and shows on screen. */ void ShowErrorMessage(const std::string &, QMessageBox::Icon = QMessageBox::Critical); /** * @brief Searches and parses paths of python virtual enviroments * from predefined lookout locations */ void AutoParsePythonPaths(); /** * @brief Clears all combo boxes * Any new combo box added in the future can be featured here for clearance. * */ void ClearAllComboBoxes(); /** * @brief Checks if nnUNet_predict command is valid in the selected python virtual environment. * * @return bool */ bool IsNNUNetInstalled(const QString &); /** * @brief Mapper function to map QString entries from UI to ModelParam attributes. * * @return mitk::ModelParams */ mitk::ModelParams MapToRequest( const QString &, const QString &, const QString &, const QString &, const std::vector &); /** * @brief Returns checked fold names from the ctk-Checkable-ComboBox. * * @return std::vector */ std::vector FetchSelectedFoldsFromUI(); /** * @brief Returns all paths from the dynamically generated ctk-path-line-edit boxes. * * @return std::vector */ std::vector FetchMultiModalImagesFromUI(); - /** - * @brief Template function to fetch all folders inside a given path. - * The type can be any of stl or Qt containers which supports push_back call. - * - * @tparam T - * @return T - */ - template - static T FetchFoldersFromDir(const QString &); - Ui_QmitknnUNetToolGUIControls m_Controls; // QThread *m_SegmentationThread; nnUNetSegmentationWorker *m_Worker; QmitkGPULoader m_GpuLoader; /** * @brief Stores all dynamically added ctk-path-line-edit UI elements. * */ std::vector m_Modalities; std::vector> m_EnsembleParams; mitk::NodePredicateBase::Pointer m_MultiModalPredicate; /** * @brief Stores row count of the "advancedSettingsLayout" layout element. This value helps dynamically add * ctk-path-line-edit UI elements at the right place. Forced to initialize in the InitializeUI method since there is * no guarantee of retrieving exact row count anywhere else. * */ int m_UI_ROWS; /** * @brief Stores path of the model director (RESULTS_FOLDER appended by "nnUNet"). * */ std::shared_ptr m_ParentFolder = nullptr; /** * @brief Valid list of models supported by nnUNet * */ const QStringList m_VALID_MODELS = {"2d", "3d_lowres", "3d_fullres", "3d_cascade_fullres", "ensembles"}; }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitknnUNetToolSlots.cpp b/Modules/SegmentationUI/Qmitk/QmitknnUNetToolSlots.cpp index 9ece90480a..a7ef0143a8 100644 --- a/Modules/SegmentationUI/Qmitk/QmitknnUNetToolSlots.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitknnUNetToolSlots.cpp @@ -1,447 +1,432 @@ #include "QmitknnUNetToolGUI.h" #include #include #include #include #include void QmitknnUNetToolGUI::EnableWidgets(bool enabled) { Superclass::EnableWidgets(enabled); } void QmitknnUNetToolGUI::ClearAllComboBoxes() { m_Controls.modelBox->clear(); m_Controls.taskBox->clear(); m_Controls.foldBox->clear(); m_Controls.trainerBox->clear(); for (std::unique_ptr &layout : m_EnsembleParams) { layout->modelBox->clear(); layout->trainerBox->clear(); layout->plannerBox->clear(); } } -template -T QmitknnUNetToolGUI::FetchFoldersFromDir(const QString &path) -{ - T folders; - for (QDirIterator it(path, QDir::AllDirs, QDirIterator::NoIteratorFlags); it.hasNext();) - { - it.next(); - if (!it.fileName().startsWith('.')) - { - folders.push_back(it.fileName()); - } - } - return folders; -} - void QmitknnUNetToolGUI::OnDirectoryChanged(const QString &resultsFolder) { m_Controls.previewButton->setEnabled(false); this->ClearAllComboBoxes(); m_ParentFolder = std::make_shared(resultsFolder); auto models = m_ParentFolder->getModelNames(); std::for_each(models.begin(), models.end(), [this](QString model) { if (m_VALID_MODELS.contains(model, Qt::CaseInsensitive)) m_Controls.modelBox->addItem(model); }); } void QmitknnUNetToolGUI::OnModelChanged(const QString &model) { if (model.isEmpty()) { return; } m_Controls.taskBox->clear(); auto tasks = m_ParentFolder->getTasksForModel(model); std::for_each(tasks.begin(), tasks.end(), [this](QString task) { m_Controls.taskBox->addItem(task); }); } void QmitknnUNetToolGUI::OnTaskChanged(const QString &task) { if (task.isEmpty()) { return; } m_Controls.trainerBox->clear(); m_Controls.plannerBox->clear(); QStringList trainerPlanners = m_ParentFolder->getTrainerPlannersForTask(task, m_Controls.modelBox->currentText()); if (m_Controls.modelBox->currentText() == "ensembles") { m_Controls.trainerBox->setVisible(false); m_Controls.trainerLabel->setVisible(false); m_Controls.plannerBox->setVisible(false); m_Controls.plannerLabel->setVisible(false); m_Controls.foldBox->setVisible(false); m_Controls.foldLabel->setVisible(false); ShowEnsembleLayout(true); QString splitterString = "--"; QStringList models, trainers, planners; foreach (QString trainerPlanner, trainerPlanners) { QStringList trainerSplitParts = trainerPlanner.split(splitterString, QString::SplitBehavior::SkipEmptyParts); foreach (QString modelSet, trainerSplitParts) { modelSet.remove("ensemble_", Qt::CaseInsensitive); QStringList splitParts = modelSet.split("__", QString::SplitBehavior::SkipEmptyParts); QString modelName = splitParts.first(); QString trainer = splitParts.at(1); QString planId = splitParts.at(2); models << modelName; trainers << trainer; planners << planId; } } trainers.removeDuplicates(); planners.removeDuplicates(); models.removeDuplicates(); for (std::unique_ptr &layout : m_EnsembleParams) { layout->modelBox->clear(); layout->trainerBox->clear(); layout->plannerBox->clear(); std::for_each(models.begin(), models.end(), [&layout, this](QString model) { if (m_VALID_MODELS.contains(model, Qt::CaseInsensitive)) layout->modelBox->addItem(model); }); std::for_each( trainers.begin(), trainers.end(), [&layout](QString trainer) { layout->trainerBox->addItem(trainer); }); std::for_each( planners.begin(), planners.end(), [&layout](QString planner) { layout->plannerBox->addItem(planner); }); } m_Controls.previewButton->setEnabled(true); } else { m_Controls.trainerBox->setVisible(true); m_Controls.trainerLabel->setVisible(true); m_Controls.plannerBox->setVisible(true); m_Controls.plannerLabel->setVisible(true); m_Controls.foldBox->setVisible(true); m_Controls.foldLabel->setVisible(true); m_Controls.previewButton->setEnabled(false); ShowEnsembleLayout(false); QString splitterString = "__"; QStringList trainers, planners; foreach (QString trainerPlanner, trainerPlanners) { trainers << trainerPlanner.split(splitterString, QString::SplitBehavior::SkipEmptyParts).first(); planners << trainerPlanner.split(splitterString, QString::SplitBehavior::SkipEmptyParts).last(); } trainers.removeDuplicates(); planners.removeDuplicates(); std::for_each( trainers.begin(), trainers.end(), [this](QString trainer) { m_Controls.trainerBox->addItem(trainer); }); std::for_each( planners.begin(), planners.end(), [this](QString planner) { m_Controls.plannerBox->addItem(planner); }); } } void QmitknnUNetToolGUI::OnTrainerChanged(const QString &plannerSelected) { if (plannerSelected.isEmpty()) { return; } m_Controls.foldBox->clear(); if (m_Controls.modelBox->currentText() != "ensembles") { auto selectedTrainer = m_Controls.trainerBox->currentText(); auto selectedTask = m_Controls.taskBox->currentText(); auto selectedModel = m_Controls.modelBox->currentText(); auto folds = m_ParentFolder->getFoldsForTrainerPlanner( selectedTrainer, plannerSelected, selectedTask, selectedModel); std::for_each(folds.begin(), folds.end(), [this](QString fold) { if (fold.startsWith("fold_", Qt::CaseInsensitive)) // imposed by nnUNet m_Controls.foldBox->addItem(fold); }); if (m_Controls.foldBox->count() != 0) { m_Controls.previewButton->setEnabled(true); } } else { m_Controls.previewButton->setEnabled(true); } } void QmitknnUNetToolGUI::OnPythonPathChanged(const QString &pyEnv) { if (pyEnv == QString("Select")) { QString path = QFileDialog::getExistingDirectory(m_Controls.pythonEnvComboBox->parentWidget(), "Python Path", "dir"); if (!path.isEmpty()) { m_Controls.pythonEnvComboBox->insertItem(0, path); m_Controls.pythonEnvComboBox->setCurrentIndex(0); } } else if (!IsNNUNetInstalled(pyEnv)) { std::string warning = "WARNING: nnUNet is not detected on the Python environment you selected. Please select another " "environment or create one. For more info refer https://github.com/MIC-DKFZ/nnUNet"; ShowErrorMessage(warning); } } void QmitknnUNetToolGUI::OnCheckBoxChanged(int state) { bool visibility = false; if (state == Qt::Checked) { visibility = true; } ctkCheckBox *box = qobject_cast(sender()); if (box != nullptr) { if (box->objectName() == QString("nopipBox")) { m_Controls.codedirectoryBox->setVisible(visibility); m_Controls.nnUnetdirLabel->setVisible(visibility); } else if (box->objectName() == QString("multiModalBox")) { m_Controls.multiModalSpinLabel->setVisible(visibility); m_Controls.multiModalSpinBox->setVisible(visibility); m_Controls.posSpinBoxLabel->setVisible(visibility); m_Controls.posSpinBox->setVisible(visibility); if (visibility) { QmitkDataStorageComboBox *defaultImage = new QmitkDataStorageComboBox(this, true); defaultImage->setObjectName(QString("multiModal_" + QString::number(0))); defaultImage->SetPredicate(this->m_MultiModalPredicate); defaultImage->setDisabled(true); mitk::nnUNetTool::Pointer tool = this->GetConnectedToolAs(); if (tool != nullptr) { defaultImage->SetDataStorage(tool->GetDataStorage()); defaultImage->SetSelectedNode(tool->GetRefNode()); } m_Controls.advancedSettingsLayout->addWidget(defaultImage, this->m_UI_ROWS + m_Modalities.size() + 1, 1, 1, 3); m_Modalities.push_back(defaultImage); m_Controls.posSpinBox->setMaximum(this->m_Modalities.size() - 1); m_UI_ROWS++; } else { OnModalitiesNumberChanged(0); m_Controls.multiModalSpinBox->setValue(0); m_Controls.posSpinBox->setMaximum(0); delete this->m_Modalities[0]; m_Modalities.pop_back(); } } } } void QmitknnUNetToolGUI::OnModalitiesNumberChanged(int num) { while (num > static_cast(this->m_Modalities.size() - 1)) { QmitkDataStorageComboBox *multiModalBox = new QmitkDataStorageComboBox(this, true); mitk::nnUNetTool::Pointer tool = this->GetConnectedToolAs(); multiModalBox->SetDataStorage(tool->GetDataStorage()); multiModalBox->SetPredicate(this->m_MultiModalPredicate); multiModalBox->setObjectName(QString("multiModal_" + QString::number(m_Modalities.size() + 1))); m_Controls.advancedSettingsLayout->addWidget(multiModalBox, this->m_UI_ROWS + m_Modalities.size() + 1, 1, 1, 3); m_Modalities.push_back(multiModalBox); } while (num < static_cast(this->m_Modalities.size() - 1) && !m_Modalities.empty()) { QmitkDataStorageComboBox *child = m_Modalities.back(); if (child->objectName() == "multiModal_0") { std::iter_swap(this->m_Modalities.end() - 2, this->m_Modalities.end() - 1); child = m_Modalities.back(); } delete child; // delete the layout item m_Modalities.pop_back(); } m_Controls.posSpinBox->setMaximum(this->m_Modalities.size() - 1); m_Controls.advancedSettingsLayout->update(); } void QmitknnUNetToolGUI::OnModalPositionChanged(int posIdx) { if (posIdx < static_cast(m_Modalities.size())) { int currPos = 0; bool stopCheck = false; // for-loop clears all widgets from the QGridLayout and also, finds the position of loaded-image widget. for (QmitkDataStorageComboBox *multiModalBox : m_Modalities) { m_Controls.advancedSettingsLayout->removeWidget(multiModalBox); multiModalBox->setParent(nullptr); if (multiModalBox->objectName() != "multiModal_0" && !stopCheck) { currPos++; } else { stopCheck = true; } } // moving the loaded-image widget to the required position std::iter_swap(this->m_Modalities.begin() + currPos, m_Modalities.begin() + posIdx); // re-adding all widgets in the order for (int i = 0; i < static_cast(m_Modalities.size()); ++i) { QmitkDataStorageComboBox *multiModalBox = m_Modalities[i]; m_Controls.advancedSettingsLayout->addWidget(multiModalBox, m_UI_ROWS + i + 1, 1, 1, 3); } m_Controls.advancedSettingsLayout->update(); } } void QmitknnUNetToolGUI::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); } std::vector QmitknnUNetToolGUI::FetchSelectedFoldsFromUI() { std::vector folds; if (!(m_Controls.foldBox->allChecked() || m_Controls.foldBox->noneChecked())) { QModelIndexList foldList = m_Controls.foldBox->checkedIndexes(); foreach (QModelIndex index, foldList) { QString foldQString = m_Controls.foldBox->itemText(index.row()).split("_", QString::SplitBehavior::SkipEmptyParts).last(); folds.push_back(foldQString.toStdString()); } } return folds; } mitk::ModelParams QmitknnUNetToolGUI::MapToRequest(const QString &modelName, const QString &taskName, const QString &trainer, const QString &planId, const std::vector &folds) { mitk::ModelParams requestObject; requestObject.model = modelName.toStdString(); requestObject.trainer = trainer.toStdString(); requestObject.planId = planId.toStdString(); requestObject.task = taskName.toStdString(); requestObject.folds = folds; return requestObject; } void QmitknnUNetToolGUI::SegmentationProcessFailed() { m_Controls.statusLabel->setText( "STATUS: Error in the segmentation process. No resulting segmentation can be loaded."); this->setCursor(Qt::ArrowCursor); std::stringstream stream; stream << "Error in the segmentation process. No resulting segmentation can be loaded."; ShowErrorMessage(stream.str()); m_Controls.stopButton->setEnabled(false); } void QmitknnUNetToolGUI::SegmentationResultHandler(mitk::nnUNetTool *tool) { tool->RenderOutputBuffer(); this->SetLabelSetPreview(tool->GetMLPreview()); m_Controls.statusLabel->setText("STATUS: Segmentation task finished successfully. Please Confirm the " "segmentation else will result in data loss"); m_Controls.stopButton->setEnabled(false); } void QmitknnUNetToolGUI::ShowEnsembleLayout(bool visible) { if (m_EnsembleParams.empty()) { ctkCollapsibleGroupBox *groupBoxModel1 = new ctkCollapsibleGroupBox(this); auto lay1 = std::make_unique(groupBoxModel1); m_EnsembleParams.push_back(std::move(lay1)); groupBoxModel1->setObjectName(QString::fromUtf8("model_1_Box")); groupBoxModel1->setTitle(QString::fromUtf8("Model 1")); groupBoxModel1->setMinimumSize(QSize(0, 0)); groupBoxModel1->setCollapsedHeight(5); groupBoxModel1->setCollapsed(false); groupBoxModel1->setFlat(true); groupBoxModel1->setAlignment(Qt::AlignRight); m_Controls.advancedSettingsLayout->addWidget(groupBoxModel1, 2, 0, 1, 2); ctkCollapsibleGroupBox *groupBoxModel2 = new ctkCollapsibleGroupBox(this); auto lay2 = std::make_unique(groupBoxModel2); m_EnsembleParams.push_back(std::move(lay2)); groupBoxModel2->setObjectName(QString::fromUtf8("model_2_Box")); groupBoxModel2->setTitle(QString::fromUtf8("Model 2")); groupBoxModel2->setMinimumSize(QSize(0, 0)); groupBoxModel2->setCollapsedHeight(5); groupBoxModel2->setCollapsed(false); groupBoxModel2->setFlat(true); groupBoxModel2->setAlignment(Qt::AlignLeft); m_Controls.advancedSettingsLayout->addWidget(groupBoxModel2, 2, 2, 1, 2); } for (std::unique_ptr &layout : m_EnsembleParams) { layout->parent->setVisible(visible); } } // void QmitknnUNetToolGUI::OnStopPressed() // { // m_Controls.previewButton->setEnabled(true); // m_Controls.stopButton->setEnabled(false); // if (m_SegmentationThread->isRunning()) // { // MITK_DEBUG << "Stopping thread..."; // m_SegmentationThread->requestInterruption(); // } // }