diff --git a/Modules/SegmentationUI/Qmitk/QmitknnUNetEnsembleLayout.h b/Modules/SegmentationUI/Qmitk/QmitknnUNetEnsembleLayout.h index 9a5f009830..4460fab5e0 100644 --- a/Modules/SegmentationUI/Qmitk/QmitknnUNetEnsembleLayout.h +++ b/Modules/SegmentationUI/Qmitk/QmitknnUNetEnsembleLayout.h @@ -1,91 +1,91 @@ /*============================================================================ 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 +found in the LICENSE file. ============================================================================*/ #ifndef QmitknnUNetEnsembleLayout_h_Included #define QmitknnUNetEnsembleLayout_h_Included #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class MITKSEGMENTATIONUI_EXPORT QmitknnUNetTaskParamsUITemplate { public: QLabel* trainerLabel; ctkComboBox* trainerBox; QLabel* plannerLabel; ctkComboBox* plannerBox; QLabel* foldLabel; ctkCheckableComboBox* foldBox; QLabel* modelLabel; ctkComboBox* modelBox; QWidget* parent; QmitknnUNetTaskParamsUITemplate(QWidget* inputGroupBox_1) { this->parent = inputGroupBox_1; QVBoxLayout* verticalLayout_x = new QVBoxLayout(inputGroupBox_1); verticalLayout_x->setObjectName(QString::fromUtf8("verticalLayout_x")); QGridLayout* g_x = new QGridLayout(); #ifndef Q_OS_MAC g_x->setSpacing(6); #endif #ifndef Q_OS_MAC g_x->setContentsMargins(0, 0, 0, 0); #endif g_x->setObjectName(QString::fromUtf8("g_2")); modelLabel = new QLabel("Configuration", inputGroupBox_1); g_x->addWidget(modelLabel, 0, 0, 1, 1); trainerLabel = new QLabel("Trainer", inputGroupBox_1); g_x->addWidget(trainerLabel, 0, 1, 1, 1); modelBox = new ctkComboBox(inputGroupBox_1); modelBox->setObjectName(QString::fromUtf8("modelBox_1")); g_x->addWidget(modelBox, 1, 0, 1, 1); trainerBox = new ctkComboBox(inputGroupBox_1); trainerBox->setObjectName(QString::fromUtf8("trainerBox_1")); g_x->addWidget(trainerBox, 1, 1, 1, 1); plannerLabel = new QLabel("Planner", inputGroupBox_1); g_x->addWidget(plannerLabel, 2, 0, 1, 1); foldLabel = new QLabel("Fold", inputGroupBox_1); g_x->addWidget(foldLabel, 2, 1, 1, 1); plannerBox = new ctkComboBox(inputGroupBox_1); plannerBox->setObjectName(QString::fromUtf8("plannerBox_1")); g_x->addWidget(plannerBox, 3, 0, 1, 1); foldBox = new ctkCheckableComboBox(inputGroupBox_1); foldBox->setObjectName(QString::fromUtf8("foldBox_1")); g_x->addWidget(foldBox, 3, 1, 1, 1); verticalLayout_x->addLayout(g_x); } void setVisible(bool visiblity) { this->parent->setVisible(visiblity); } }; QT_END_NAMESPACE #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitknnUNetFolderParser.h b/Modules/SegmentationUI/Qmitk/QmitknnUNetFolderParser.h index 9e77cdcae0..bdbf33508c 100644 --- a/Modules/SegmentationUI/Qmitk/QmitknnUNetFolderParser.h +++ b/Modules/SegmentationUI/Qmitk/QmitknnUNetFolderParser.h @@ -1,259 +1,259 @@ /*============================================================================ 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 +found in the LICENSE file. ============================================================================*/ #ifndef QmitknnUNetFolderParser_h_Included #define QmitknnUNetFolderParser_h_Included #include #include #include #include #include /** * @brief Struct to store each (Folder) Node of the hierarchy tree structure. * */ struct FolderNode { QString name; QString path; // parent std::vector> subFolders; }; /** * @brief Class to store and retreive folder hierarchy information * of RESULTS_FOLDER. Only Root node is explicitly stored in m_RootNode. * No. of sub levels in the hierachry is defined in the LEVEL constant. * */ class QmitknnUNetFolderParser { public: /** * @brief Construct a new QmitknnUNetFolderParser object * Initializes root folder node object pointer calls * @param parentFolder */ QmitknnUNetFolderParser(const QString parentFolder); /** * @brief Destroy the QmitknnUNetFolderParser object * */ ~QmitknnUNetFolderParser() = default; /** * @brief Returns the "Results Folder" string which is parent path of the root node. * * @return QString */ QString getResultsFolder(); /** * @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 (any of stl or Qt containers which supports push_back call) */ template T getModelNames() { 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 * @param modelName * @return T (any of stl or Qt containers which supports push_back call) */ template T getTasksForModel(const QString &modelName) { std::shared_ptr modelNode = GetSubNodeMatchingNameCrietria(modelName, m_RootNode); 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 * @param taskName * @return T (any of stl or Qt containers which supports push_back call) */ template T getModelsForTask(const QString &taskName) { 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 all the task names present in the root node with possible duplicates. * Template function, type can be any of stl or Qt containers which supports push_back call. * * @param T * @param taskName * @return T (any of stl or Qt containers which supports push_back call) */ template T getAllTasks() { T allTasks; auto models = GetSubFolderNamesFromNode(m_RootNode); foreach (QString model, models) { allTasks << getTasksForModel(model); } return allTasks; } /** * @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 * @param taskName * @param modelName * @return T (any of stl or Qt containers which supports push_back call) */ template T getTrainerPlannersForTask(const QString &taskName, const QString &modelName) { std::shared_ptr modelNode = GetSubNodeMatchingNameCrietria(modelName, m_RootNode); std::shared_ptr taskNode = GetSubNodeMatchingNameCrietria(taskName, modelNode); 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 * @param trainer * @param planner * @param taskName * @param modelName * @return T (any of stl or Qt containers which supports push_back call) */ template T getFoldsForTrainerPlanner(const QString &trainer, const QString &planner, const QString &taskName, const QString &modelName) { 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); auto folds = GetSubFolderNamesFromNode(tpNode); return folds; } private: const int m_LEVEL = 4; std::shared_ptr m_RootNode; /** * @brief Returns rule function wrapper to check for specific files at given Result_Folder hierarchy level. * * @param level * @return std::function */ std::function RuleEngine(int level); /** * @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); /** * @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 * @param std::shared_ptr * @return T (any of stl or Qt containers which supports push_back call) */ 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); /** * @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); /** * @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, std::function callback) { T folders; for (QDirIterator it(path, QDir::AllDirs, QDirIterator::NoIteratorFlags); it.hasNext();) { it.next(); if (!it.fileName().startsWith('.') && callback(it.filePath())) { folders.push_back(it.fileName()); } } return folders; } }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitknnUNetGPU.h b/Modules/SegmentationUI/Qmitk/QmitknnUNetGPU.h index b7f0ccbf7d..035f7f7e99 100644 --- a/Modules/SegmentationUI/Qmitk/QmitknnUNetGPU.h +++ b/Modules/SegmentationUI/Qmitk/QmitknnUNetGPU.h @@ -1,63 +1,63 @@ /*============================================================================ 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 +found in the LICENSE file. ============================================================================*/ #ifndef QmitknnUNetToolGPU_h_Included #define QmitknnUNetToolGPU_h_Included #include #include #include /** * @brief Struct to store GPU info. * */ struct QmitkGPUSpec { QString name; QString memory; unsigned int id; }; /** * @brief Class to load and save GPU information * for further validation */ class MITKSEGMENTATIONUI_EXPORT QmitkGPULoader { private: std::vector m_Gpus; public: /** * @brief Construct a new Qmitk GPU Loader object. * Parses GPU info using `nvidia-smi` command and saves it as QmitkGPUSpec objects. */ QmitkGPULoader(); ~QmitkGPULoader() = default; /** * @brief Returns the number of GPUs parsed and saved as QmitkGPUSpec objects. * * @return int */ int GetGPUCount(); /** * @brief Returns all the parsed GPU information * * @return std::vector */ std::vector GetAllGPUSpecs(); }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUI.h b/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUI.h index 2b9ce14db5..bdd40f033a 100644 --- a/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUI.h +++ b/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUI.h @@ -1,405 +1,405 @@ /*============================================================================ 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 +found in the LICENSE file. ============================================================================*/ #ifndef QmitknnUNetToolGUI_h_Included #define QmitknnUNetToolGUI_h_Included #include "QmitkMultiLabelSegWithPreviewToolGUIBase.h" #include "QmitknnUNetFolderParser.h" #include "QmitknnUNetGPU.h" #include "QmitknnUNetWorker.h" #include "mitkProcessExecutor.h" #include "mitknnUnetTool.h" #include "ui_QmitknnUNetToolGUIControls.h" #include #include #include #include #include #include #include #include #include class nnUNetCache { public: mitk::LabelSetImage::ConstPointer m_SegCache; static size_t GetUniqueHash(std::vector &requestQ) { size_t hashCode = 0; for (mitk::ModelParams &request : requestQ) { boost::hash_combine(hashCode, request.generateHash()); } return hashCode; } }; class MITKSEGMENTATIONUI_EXPORT QmitknnUNetToolGUI : public QmitkMultiLabelSegWithPreviewToolGUIBase { Q_OBJECT public: mitkClassMacro(QmitknnUNetToolGUI, QmitkMultiLabelSegWithPreviewToolGUIBase); itkFactorylessNewMacro(Self); itkCloneMacro(Self); QCache m_Cache; /** * @brief The hash map stores all bifurcating processes' ID. * */ std::unordered_map m_Processes; 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 *, bool forceRender = false); /** * @brief Qt Slot * */ void OnModalitiesNumberChanged(int); /** * @brief Qt Slot * */ void OnPythonPathChanged(const QString&); /** * @brief Qt slot * */ void OnRefreshPresssed(); /** * @brief Qt slot * */ void OnClearCachePressed(); /** * @brief Qt slot * */ void OnDownloadModel(); /** * @brief Qt slot * */ void OnDownloadWorkerExit(bool, const QString); /** * @brief Qt slot * */ void OnStopDownload(); signals: /** * @brief signal for starting the segmentation which is caught by a worker thread. */ void Operate(QString, QString, mitk::ProcessExecutor::Pointer, mitk::ProcessExecutor::ArgumentListType); protected: QmitknnUNetToolGUI(); ~QmitknnUNetToolGUI(); void ConnectNewTool(mitk::SegWithPreviewTool* newTool) override; void InitializeUI(QBoxLayout* mainLayout) override; void EnableWidgets(bool enabled) override; private: /** * @brief Adds an element and hides it so that the ctkCheckableComboBox shows "None". */ void SetComboBoxToNone(ctkCheckableComboBox*); /** * @brief Parses the available_models.json file from RESULTS_FOLDER and loads * the task names to the Download combobox in Advanced. */ void FillAvailableModelsInfoFromJSON(const QString&); /** * @brief Exports available models to download from nnUNet_print_available_pretrained_models * output. */ void ExportAvailableModelsAsJSON(const QString&); /** * @brief Clears all displayed modal labels and widgets from GUI. * */ void ClearAllModalities(); /** * @brief Parses Json file containing modality info and populates * labels and selection widgets accordingly on the GUI. */ void DisplayMultiModalInfoFromJSON(const QString&); /** * @brief Clears all modality labels previously populated from GUI. * */ void ClearAllModalLabels(); /** * @brief Runs a set of python commands to read "plans.pkl" and extract * modality information required for inferencing. This information is exported * as json file : "mitk_export.json". * * @return QString */ void DumpJSONfromPickle(const QString&); /** * @brief Searches RESULTS_FOLDER environment variable. If not found, * returns from the QSettings stored last used path value. * @return QString */ QString FetchResultsFolderFromEnv(); /** * @brief Returns GPU id of the selected GPU from the Combo box. * * @return unsigned int */ unsigned int FetchSelectedGPUFromUI(); /** * @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 Inserts the hash and segmentation into cache and * updates count on UI. */ void AddToCache(size_t&, mitk::LabelSetImage::ConstPointer); /** * @brief Checks all the entries of the ctkCheckableComboBox ui widget. * This feature is not present in ctkCheckableComboBox API. */ void CheckAllInCheckableComboBox(ctkCheckableComboBox*); /** * @brief Parses the folder names containing trainer and planner together and, * returns it as separate lists. * @return std::pair */ std::pair ExtractTrainerPlannerFromString(QStringList); /** * @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 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 Searches and parses paths of python virtual enviroments * from predefined lookout locations */ void AutoParsePythonPaths(); /** * @brief Check if pretrained model sub folder inside RESULTS FOLDER exist. */ bool IsModelExists(const QString&, const QString&, const QString&); /** * @brief Clears all combo boxes * Any new combo box added in the future can be featured here for clearance. * */ void ClearAllComboBoxes(); /** * @brief Disable/deactivates the nnUNet GUI. * Clears any multi modal labels and selection widgets, as well. */ void DisableEverything(); /** * @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(ctkCheckableComboBox*); /** * @brief Returns all paths from the dynamically generated ctk-path-line-edit boxes. * * @return std::vector */ std::vector FetchMultiModalImagesFromUI(); /** * @brief Updates cache count on UI. * */ void UpdateCacheCountOnUI(); Ui_QmitknnUNetToolGUIControls m_Controls; QmitkGPULoader m_GpuLoader; /** * @brief Stores all dynamically added ctk-path-line-edit UI elements. * */ std::vector m_Modalities; std::vector m_ModalLabels; std::vector> m_EnsembleParams; mitk::NodePredicateBase::Pointer m_MultiModalPredicate; QString m_PythonPath; /** * @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"}; const QString m_CACHE_COUNT_BASE_LABEL = "Cached Items: "; const QString m_MITK_EXPORT_JSON_FILENAME = "mitk_export.json"; const QString m_AVAILABLE_MODELS_JSON_FILENAME = "available_models.json"; const QString m_PICKLE_FILENAME = "plans.pkl"; /** * @brief For storing values across sessions. Currently, RESULTS_FOLDER value is cached using this. */ QSettings m_Settings; bool m_IsResultsFolderValid = false; QThread* m_nnUNetThread; nnUNetDownloadWorker* m_Worker; bool m_FirstPreviewComputation = true; EnableConfirmSegBtnFunctionType m_SuperclassEnableConfirmSegBtnFnc; }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitknnUNetWorker.h b/Modules/SegmentationUI/Qmitk/QmitknnUNetWorker.h index fe00b728f4..c99aeb7a4c 100644 --- a/Modules/SegmentationUI/Qmitk/QmitknnUNetWorker.h +++ b/Modules/SegmentationUI/Qmitk/QmitknnUNetWorker.h @@ -1,51 +1,51 @@ /*============================================================================ 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 +found in the LICENSE file. ============================================================================*/ #ifndef QmitknnUNetWorker_h #define QmitknnUNetWorker_h #include "mitkProcessExecutor.h" #include #include Q_DECLARE_METATYPE(mitk::ProcessExecutor::Pointer); Q_DECLARE_METATYPE(mitk::ProcessExecutor::ArgumentListType); /** * @brief Class to execute some functions from the Segmentation Plugin in a seperate thread */ class nnUNetDownloadWorker : public QObject { Q_OBJECT public slots: /** * @brief Starts the download process worker thread. * */ void DoWork(QString, QString, mitk::ProcessExecutor::Pointer, mitk::ProcessExecutor::ArgumentListType); signals: /** * @brief the signal emitted when a download process is finshed; success or failed * * @param exitCode * @param message */ void Exit(bool exitCode, const QString message); private: QMutex mutex; }; #endif