diff --git a/Modules/Segmentation/Interactions/mitkTotalSegmentatorTool.h b/Modules/Segmentation/Interactions/mitkTotalSegmentatorTool.h index 7553739a8c..5124a5b568 100644 --- a/Modules/Segmentation/Interactions/mitkTotalSegmentatorTool.h +++ b/Modules/Segmentation/Interactions/mitkTotalSegmentatorTool.h @@ -1,130 +1,135 @@ /*============================================================================ 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 MITKTOTALSEGMENTATORTOOL_H #define MITKTOTALSEGMENTATORTOOL_H #include "mitkSegWithPreviewTool.h" #include #include "mitkProcessExecutor.h" namespace us { class ModuleResource; } namespace mitk { /** \brief TotalSegmentator segmentation tool. \ingroup Interaction \ingroup ToolManagerEtAl \warning Only to be instantiated by mitk::ToolManager. */ class MITKSEGMENTATION_EXPORT TotalSegmentatorTool : public SegWithPreviewTool { public: mitkClassMacro(TotalSegmentatorTool, SegWithPreviewTool); itkFactorylessNewMacro(Self); itkCloneMacro(Self); const char *GetName() const override; const char **GetXPM() const override; us::ModuleResource GetIconResource() const override; void Activated() override; itkSetMacro(MitkTempDir, std::string); itkGetConstMacro(MitkTempDir, std::string); itkSetMacro(SubTask, std::string); itkGetConstMacro(SubTask, std::string); itkSetMacro(PythonPath, std::string); itkGetConstMacro(PythonPath, std::string); itkSetMacro(GpuId, unsigned int); itkGetConstMacro(GpuId, unsigned int); itkSetMacro(Fast, bool); itkGetConstMacro(Fast, bool); itkBooleanMacro(Fast); itkSetMacro(IsMitkTempDirAvailable, bool); itkGetConstMacro(IsMitkTempDirAvailable, bool); itkBooleanMacro(IsMitkTempDirAvailable); - static void onPythonProcessEvent(itk::Object * /*pCaller*/, const itk::EventObject &e, void *); + /** + * @brief Static function to print out everything from itk::EventObject. + * Used as callback in mitk::ProcessExecutor object. + * + */ + static void onPythonProcessEvent(itk::Object *, const itk::EventObject &e, void *); protected: TotalSegmentatorTool() = default; ~TotalSegmentatorTool(); /** * @brief Overriden method from the tool manager to execute the segmentation * Implementation: * 1. Creates temp directory, if not done already. * 2. Parses Label names from map_to_binary.py for using later on. * 3. Calls "run_totalsegmentator" method. * 4. Expects an output image to be saved in the temporary directory by the python proces. Loads it as * LabelSetImage and sets to previewImage. * * @param inputAtTimeStep * @param oldSegAtTimeStep * @param previewImage * @param timeStep */ void DoUpdatePreview(const Image* inputAtTimeStep, const Image* oldSegAtTimeStep, LabelSetImage* previewImage, TimeStepType timeStep) override; private: /** * @brief Runs Totalsegmentator python process with desired arguments * */ void run_totalsegmentator(ProcessExecutor::Pointer, const std::string &, const std::string &, bool, bool, unsigned int, const std::string &); /** * @brief Applies the m_LabelMapTotal lookup table on the output segmentation LabelSetImage. * */ void MapLabelsToSegmentation(mitk::LabelSetImage::Pointer, std::map&); /** * @brief Parses map_to_binary.py file to extract label ids and names * and stores as a map for reference in m_LabelMapTotal * * @param filePath */ void ParseLabelNames(const std::string &); /** * @brief Get the Label Map Path from the virtual environment location * * @return std::string */ std::string GetLabelMapPath(); std::string m_MitkTempDir; std::string m_PythonPath; std::string m_SubTask = "total"; unsigned int m_GpuId; std::map m_LabelMapTotal; bool m_Fast; bool m_IsMitkTempDirAvailable = false; const std::string m_TEMPLATE_FILENAME = "XXXXXX_000_0000.nii.gz"; const std::string m_DEFAULT_TOTAL_TASK = "total"; }; // class } // namespace #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.h b/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.h index 3adcbae926..748334bc45 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.h +++ b/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.h @@ -1,76 +1,195 @@ /*============================================================================ 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 "mitkLogMacros.h" #include "mitkProcessExecutor.h" #include #include #include #include /** - * @brief Super Class to Setup a python virtual environment and pip install required packages + * @brief Abstract Class to Setup a python virtual environment and pip install required packages. + * Derive this class for creating installer for the respective tool. */ class MITKSEGMENTATIONUI_EXPORT QmitkSetupVirtualEnvUtil { public: QmitkSetupVirtualEnvUtil(const QString& baseDir); QmitkSetupVirtualEnvUtil(); + /** + * @brief Implement the method in child class + * to setup the virtual environment. + */ virtual bool SetupVirtualEnv(const QString& venvName) = 0; + + /** + * @brief Get the Virtual Env Path object. Override this method in the respective + * tool installer class. + * + * @return QString + */ virtual QString GetVirtualEnvPath(); + /** + * @brief Function to Pip install a library package given the location of + * pip3 executable. + * Any callback function can be passed to process the output. + * + * @param library + * @param workingDir + * @param callback + * @param command + */ void PipInstall(const std::string &library, const std::string &workingDir, void (*callback)(itk::Object *, const itk::EventObject &, void *), const std::string &command = "pip3"); + /** + * @brief Overloaded function to Pip install a library function. + * + * @param library + * @param callback + * @param command + */ void PipInstall(const std::string &library, void (*callback)(itk::Object *, const itk::EventObject &, void *), const std::string &command = "pip3"); + /** + * @brief Function to execute any python code given a python path. + * Any callback function can be passed to process the output. + * + * @param args + * @param pythonPath + * @param callback + * @param command + */ void ExecutePython(const std::string &args, const std::string &pythonPath, void (*callback)(itk::Object *, const itk::EventObject &, void *), const std::string &command = "python"); + /** + * @brief Overloaded function to Execute Python code. + * Any callback function can be passed to process the output. + * + * @param args + * @param callback + * @param command + */ void ExecutePython(const std::string &args, void (*callback)(itk::Object *, const itk::EventObject &, void *), const std::string &command = "python"); + /** + * @brief Installs pytorch using light-the-torch package, correctly identifying cuda version. + * Requires location of pip3 executable. + * Any callback function can be passed to process the output. + * + * @param workingDir + * @param callback + */ void InstallPytorch(const std::string &workingDir, void (*callback)(itk::Object *, const itk::EventObject &, void *)); + + /** + * @brief Overloaded function to install pytorch using light-the-torch package, correctly + * identifying cuda version. + */ void InstallPytorch(); + /** + * @brief Get the Base Dir object + * + * @return QString& + */ QString& GetBaseDir(); + + /** + * @brief Get the System Python Path object + * + * @return QString& + */ QString& GetSystemPythonPath(); + + /** + * @brief Get the Python Path object + * + * @return QString& + */ QString& GetPythonPath(); + + /** + * @brief Get the Pip Path object + * + * @return QString& + */ QString& GetPipPath(); + + /** + * @brief Set the System Python Path object + * + * @param path + */ void SetSystemPythonPath(const QString& path); + + /** + * @brief Set the Python Path object + * + * @param path + */ void SetPythonPath(const QString& path); + + /** + * @brief Set the Pip Path object + * + * @param path + */ void SetPipPath(const QString& path); + + /** + * @brief Set the Virtual Env Path object + * + * @param path + */ void SetVirtualEnvPath(const QString &path); + /** + * @brief Check if the path provide has python executable or not. + * + * @param pythonPath + * @return true + * @return false + */ bool IsPythonPath(const QString &pythonPath); - static void PrintProcessEvent(itk::Object * /*pCaller*/, const itk::EventObject &e, void *); + + /** + * @brief Function can be used as callback to simply print out all the process execution output + * parsed out from itk::EventObject. + * + */ + static void PrintProcessEvent(itk::Object *, const itk::EventObject &e, void *); private: QString m_PythonPath; QString m_PipPath; QString m_BaseDir; QString m_venvPath; QString m_SysPythonPath; }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.h b/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.h index f3f02cb603..0196b9e150 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.h +++ b/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.h @@ -1,151 +1,170 @@ #ifndef QmitkTotalSegmentatorToolGUI_h_Included #define QmitkTotalSegmentatorToolGUI_h_Included #include "QmitkMultiLabelSegWithPreviewToolGUIBase.h" #include "QmitkSetupVirtualEnvUtil.h" #include "QmitknnUNetGPU.h" #include "ui_QmitkTotalSegmentatorGUIControls.h" #include #include #include #include +/** + * @brief Installer class for TotalSegmentator Tool. + * Class specifies the virtual environment name, install version, packages required to pip install + * and implements SetupVirtualEnv method. + * + */ class QmitkTotalSegmentatorToolInstaller : public QmitkSetupVirtualEnvUtil { public: const QString m_VENV_NAME = ".totalsegmentator"; const QString m_TOTALSEGMENTATOR_VERSION = "1.5.3"; const std::vector m_PACKAGES = {QString("Totalsegmentator==") + m_TOTALSEGMENTATOR_VERSION, QString("scipy==1.9.1")}; const QString m_STORAGE_DIR; inline QmitkTotalSegmentatorToolInstaller( const QString baseDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QDir::separator() + qApp->organizationName() + QDir::separator()) : QmitkSetupVirtualEnvUtil(baseDir), m_STORAGE_DIR(baseDir){}; bool SetupVirtualEnv(const QString &) override; QString GetVirtualEnvPath() override; }; +/** + \ingroup org_mitk_gui_qt_interactivesegmentation_internal + \brief GUI for mitk::TotalSegmentatorTool. + \sa mitk:: +*/ 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 */ QString OnSystemPythonChanged(const QString &); /** * @brief Qt Slot */ void OnInstallBtnClicked(); /** * @brief Qt Slot */ void OnOverrideChecked(int); /** * @brief Qt Slot */ void OnClearInstall(); 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 Get the virtual env path from UI combobox removing any + * extra special characters. + * + * @return QString + */ QString GetPythonPathFromUI(const QString &); + /** + * @brief Get the Exact Python Path for any OS + * from the virtual environment path. + * @return QString + */ QString GetExactPythonPath(const QString &); /** * @brief For storing values like Python path across sessions. */ QSettings m_Settings; QString m_PythonPath; 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"}; QmitkTotalSegmentatorToolInstaller m_Installer; }; #endif