diff --git a/Modules/Segmentation/Interactions/mitkMedSAMTool.cpp b/Modules/Segmentation/Interactions/mitkMedSAMTool.cpp index daace744a4..c70ae77226 100644 --- a/Modules/Segmentation/Interactions/mitkMedSAMTool.cpp +++ b/Modules/Segmentation/Interactions/mitkMedSAMTool.cpp @@ -1,146 +1,144 @@ /*============================================================================ 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 "mitkMedSAMTool.h" #include "mitkToolManager.h" #include "mitkGeometryData.h" #include "mitkInteractionPositionEvent.h" // us #include #include #include #include using namespace std::chrono_literals; namespace mitk { MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, MedSAMTool, "MedSAMTool"); } const char *mitk::MedSAMTool::GetName() const { return "MedSAM"; } void mitk::MedSAMTool::Activated() { SegWithPreviewTool::Activated(); this->SetLabelTransferScope(LabelTransferScope::ActiveLabel); this->SetLabelTransferMode(LabelTransferMode::MapLabel); } void mitk::MedSAMTool::Deactivated() { SegWithPreviewTool::Deactivated(); GetDataStorage()->Remove(m_BoundingBoxNode); m_BoundingBoxNode = nullptr; m_PythonService.reset(); } void mitk::MedSAMTool::ConnectActionsAndFunctions() { CONNECT_FUNCTION("ShiftPrimaryButtonPressed", OnRenderWindowClicked); CONNECT_FUNCTION("DeletePoint", OnDelete); } void mitk::MedSAMTool::OnRenderWindowClicked(StateMachineAction *, InteractionEvent *interactionEvent) { if (!this->GetIsReady()) { return; } if ((nullptr == this->GetWorkingPlaneGeometry()) || !mitk::Equal(*(interactionEvent->GetSender()->GetCurrentWorldPlaneGeometry()), *(this->GetWorkingPlaneGeometry()))) { this->GetDataStorage()->Remove(m_BoundingBoxNode); m_BoundingBoxNode = nullptr; this->SetWorkingPlaneGeometry(interactionEvent->GetSender()->GetCurrentWorldPlaneGeometry()->Clone()); auto boundingBox = mitk::GeometryData::New(); boundingBox->SetGeometry(static_cast( this->InitializeWithImageGeometry(interactionEvent->GetSender()->GetCurrentWorldPlaneGeometry()->Clone()))); m_BoundingBoxNode = mitk::DataNode::New(); m_BoundingBoxNode->SetData(boundingBox); m_BoundingBoxNode->SetVisibility(true); m_BoundingBoxNode->SetName(std::string(this->GetName()) + "_Boundingbox"); m_BoundingBoxNode->SetProperty("layer", mitk::IntProperty::New(99)); m_BoundingBoxNode->AddProperty("Bounding Shape.Handle Size Factor", mitk::DoubleProperty::New(0.02)); m_BoundingBoxNode->SetBoolProperty("pickable", true); this->GetDataStorage()->Add(m_BoundingBoxNode, this->GetToolManager()->GetWorkingData(0)); this->CreateBoundingShapeInteractor(false); m_BoundingShapeInteractor->EnableInteraction(true); m_BoundingShapeInteractor->SetDataNode(m_BoundingBoxNode); mitk::RenderingManager::GetInstance()->InitializeViews(); } } void mitk::MedSAMTool::CreateBoundingShapeInteractor(bool rotationEnabled) { if (m_BoundingShapeInteractor.IsNull()) { m_BoundingShapeInteractor = mitk::BoundingShapeInteractor::New(); m_BoundingShapeInteractor->LoadStateMachine("BoundingShapeInteraction.xml", us::ModuleRegistry::GetModule("MitkBoundingShape")); m_BoundingShapeInteractor->SetEventConfig("BoundingShapeMouseConfig.xml", us::ModuleRegistry::GetModule("MitkBoundingShape")); } m_BoundingShapeInteractor->SetRotationEnabled(rotationEnabled); } mitk::Geometry3D::Pointer mitk::MedSAMTool::InitializeWithImageGeometry(const mitk::BaseGeometry *geometry) const { - // convert a BaseGeometry into a Geometry3D (otherwise IO is not working properly) if (geometry == nullptr) mitkThrow() << "Geometry is not valid."; - auto boundingGeometry = mitk::Geometry3D::New(); boundingGeometry->SetBounds(geometry->GetBounds()); boundingGeometry->SetImageGeometry(geometry->GetImageGeometry()); boundingGeometry->SetOrigin(geometry->GetOrigin()); boundingGeometry->SetSpacing(geometry->GetSpacing()); boundingGeometry->SetIndexToWorldTransform(geometry->GetIndexToWorldTransform()->Clone()); boundingGeometry->Modified(); return boundingGeometry; } bool mitk::MedSAMTool::HasPicks() const { return m_BoundingBoxNode.IsNotNull(); } void mitk::MedSAMTool::OnDelete(StateMachineAction*, InteractionEvent*) { this->ClearPicks(); } void mitk::MedSAMTool::ClearPicks() { this->GetDataStorage()->Remove(m_BoundingBoxNode); m_BoundingBoxNode = nullptr; } std::stringstream mitk::MedSAMTool::GetPointsAsCSVString(const mitk::BaseGeometry * /*baseGeometry*/) { auto geometry = m_BoundingBoxNode->GetData()->GetGeometry(); mitk::BoundingBox::ConstPointer boundingBox = geometry->GetBoundingBox(); mitk::Point3D BBmin = boundingBox->GetMinimum(); mitk::Point3D BBmax = boundingBox->GetMaximum(); std::stringstream pointsAndLabels; pointsAndLabels << "Coordinates\n"; const char SPACE = ' '; pointsAndLabels << abs(static_cast(BBmin[0])) << SPACE << abs(static_cast(BBmin[1])) << SPACE << abs(static_cast(BBmax[0])) << SPACE << abs(static_cast(BBmax[1])); return pointsAndLabels; } diff --git a/Modules/Segmentation/Interactions/mitkMedSAMTool.h b/Modules/Segmentation/Interactions/mitkMedSAMTool.h index 7b9394e8da..40dc2170a9 100644 --- a/Modules/Segmentation/Interactions/mitkMedSAMTool.h +++ b/Modules/Segmentation/Interactions/mitkMedSAMTool.h @@ -1,66 +1,84 @@ /*============================================================================ 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 mitkMedSAMTool_h #define mitkMedSAMTool_h #include "mitkSegmentAnythingTool.h" #include "mitkBoundingShapeInteractor.h" #include #include namespace us { class ModuleResource; } namespace mitk { /** \brief Medical Segment Anything Model interactive 2D tool class. \ingroup ToolManagerEtAl \sa mitk::Tool \sa QmitkInteractiveSegmentation */ class MITKSEGMENTATION_EXPORT MedSAMTool : public SegmentAnythingTool { public: mitkClassMacro(MedSAMTool, SegmentAnythingTool); itkFactorylessNewMacro(Self); itkCloneMacro(Self); const char *GetName() const override; void Activated() override; void Deactivated() override; bool HasPicks() const override; void ClearPicks() override; void ConnectActionsAndFunctions() override; + std::stringstream GetPointsAsCSVString(const mitk::BaseGeometry *) override; + + /** + * @brief Adds bounding box in the render window when clicked. + * + */ void OnRenderWindowClicked(StateMachineAction *, InteractionEvent *); + + /** + * @brief Deletes bounding box from the render window. + * + */ void OnDelete(StateMachineAction *, InteractionEvent *); - std::stringstream GetPointsAsCSVString(const mitk::BaseGeometry *); protected: MedSAMTool() = default; ~MedSAMTool() = default; private: + /** + * @brief Initializes the Bounding Shape Interactor object + * + */ void CreateBoundingShapeInteractor(bool); + + /** + * @brief initializes a new bounding shape using the selected image geometry. + * + */ mitk::Geometry3D::Pointer InitializeWithImageGeometry(const mitk::BaseGeometry *) const; DataNode::Pointer m_BoundingBoxNode; BoundingShapeInteractor::Pointer m_BoundingShapeInteractor; }; -} // namespace - +} #endif diff --git a/Modules/Segmentation/Interactions/mitkSegmentAnythingPythonService.cpp b/Modules/Segmentation/Interactions/mitkSegmentAnythingPythonService.cpp index b4edd59be9..d88d00d4c8 100644 --- a/Modules/Segmentation/Interactions/mitkSegmentAnythingPythonService.cpp +++ b/Modules/Segmentation/Interactions/mitkSegmentAnythingPythonService.cpp @@ -1,269 +1,269 @@ /*============================================================================ 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 "mitkSegmentAnythingPythonService.h" #include "mitkIOUtil.h" #include #include #include #include #include #include #include "mitkImageAccessByItk.h" #include using namespace std::chrono_literals; using sys_clock = std::chrono::system_clock; namespace mitk { const std::string SIGNALCONSTANTS::READY = "READY"; const std::string SIGNALCONSTANTS::KILL = "KILL"; const std::string SIGNALCONSTANTS::OFF = "OFF"; const std::string SIGNALCONSTANTS::CUDA_OUT_OF_MEMORY_ERROR = "CudaOutOfMemoryError"; const std::string SIGNALCONSTANTS::TIMEOUT_ERROR = "TimeOut"; SegmentAnythingPythonService::Status SegmentAnythingPythonService::CurrentStatus = SegmentAnythingPythonService::Status::OFF; } mitk::SegmentAnythingPythonService::SegmentAnythingPythonService( std::string workingDir, std::string modelType, std::string checkPointPath, unsigned int gpuId, std::string backend) : m_PythonPath(workingDir), m_ModelType(modelType), m_CheckpointPath(checkPointPath), - m_GpuId(gpuId), - m_Backend(backend) + m_Backend(backend), + m_GpuId(gpuId) { this->CreateTempDirs(PARENT_TEMP_DIR_PATTERN); } mitk::SegmentAnythingPythonService::~SegmentAnythingPythonService() { if (CurrentStatus == Status::READY) { this->StopAsyncProcess(); } CurrentStatus = Status::OFF; std::filesystem::remove_all(this->GetMitkTempDir()); } void mitk::SegmentAnythingPythonService::onPythonProcessEvent(itk::Object*, const itk::EventObject &e, void*) { std::string testCOUT,testCERR; const auto *pEvent = dynamic_cast(&e); if (pEvent) { testCOUT = testCOUT + pEvent->GetOutput(); testCOUT.erase(std::find_if(testCOUT.rbegin(), testCOUT.rend(), [](unsigned char ch) { return !std::isspace(ch);}).base(), testCOUT.end()); // remove trailing whitespaces, if any if (SIGNALCONSTANTS::READY == testCOUT) { CurrentStatus = Status::READY; } if (SIGNALCONSTANTS::KILL == testCOUT) { CurrentStatus = Status::KILLED; } if (SIGNALCONSTANTS::CUDA_OUT_OF_MEMORY_ERROR == testCOUT) { CurrentStatus = Status::CUDAError; } MITK_INFO << testCOUT; } const auto *pErrEvent = dynamic_cast(&e); if (pErrEvent) { testCERR = testCERR + pErrEvent->GetOutput(); MITK_ERROR << testCERR; } } void mitk::SegmentAnythingPythonService::StopAsyncProcess() { std::stringstream controlStream; controlStream << SIGNALCONSTANTS::KILL; this->WriteControlFile(controlStream); m_DaemonExec->SetStop(true); m_Future.get(); } void mitk::SegmentAnythingPythonService::StartAsyncProcess() { if (nullptr != m_DaemonExec) { this->StopAsyncProcess(); } if (this->GetMitkTempDir().empty()) { this->CreateTempDirs(PARENT_TEMP_DIR_PATTERN); } std::stringstream controlStream; controlStream << SIGNALCONSTANTS::READY; this->WriteControlFile(controlStream); double timeout = 1; m_DaemonExec = SegmentAnythingProcessExecutor::New(timeout); itk::CStyleCommand::Pointer spCommand = itk::CStyleCommand::New(); spCommand->SetCallback(&mitk::SegmentAnythingPythonService::onPythonProcessEvent); m_DaemonExec->AddObserver(ExternalProcessOutputEvent(), spCommand); m_Future = std::async(std::launch::async, &mitk::SegmentAnythingPythonService::start_python_daemon, this); } void mitk::SegmentAnythingPythonService::TransferPointsToProcess(std::stringstream &triggerCSV) { this->CheckStatus(); std::string triggerFilePath = m_InDir + IOUtil::GetDirectorySeparator() + TRIGGER_FILENAME; std::ofstream csvfile; csvfile.open(triggerFilePath, std::ofstream::out | std::ofstream::trunc); csvfile << triggerCSV.rdbuf(); csvfile.close(); } void mitk::SegmentAnythingPythonService::WriteControlFile(std::stringstream &statusStream) { std::string controlFilePath = m_InDir + IOUtil::GetDirectorySeparator() + "control.txt"; std::ofstream controlFile; controlFile.open(controlFilePath, std::ofstream::out | std::ofstream::trunc); controlFile << statusStream.rdbuf(); controlFile.close(); } void mitk::SegmentAnythingPythonService::start_python_daemon() { ProcessExecutor::ArgumentListType args; std::string command = "python"; args.push_back("-u"); args.push_back(SAM_PYTHON_FILE_NAME); args.push_back("--input-folder"); args.push_back(m_InDir); args.push_back("--output-folder"); args.push_back(m_OutDir); args.push_back("--trigger-file"); args.push_back(TRIGGER_FILENAME); args.push_back("--model-type"); args.push_back(m_ModelType); args.push_back("--checkpoint"); args.push_back(m_CheckpointPath); args.push_back("--backend"); args.push_back(m_Backend); args.push_back("--device"); if (m_GpuId == -1) { args.push_back("cpu"); } else { args.push_back("cuda"); std::string cudaEnv = "CUDA_VISIBLE_DEVICES=" + std::to_string(m_GpuId); itksys::SystemTools::PutEnv(cudaEnv.c_str()); } try { std::stringstream logStream; for (const auto &arg : args) logStream << arg << " "; logStream << m_PythonPath; MITK_INFO << logStream.str(); m_DaemonExec->Execute(m_PythonPath, command, args); } catch (const mitk::Exception &e) { MITK_ERROR << e.GetDescription(); return; } MITK_INFO << "Python process ended."; } bool mitk::SegmentAnythingPythonService::CheckStatus() { switch (CurrentStatus) { case mitk::SegmentAnythingPythonService::Status::READY: return true; case mitk::SegmentAnythingPythonService::Status::CUDAError: mitkThrow() << "Error: Cuda Out of Memory. Change your model type in Preferences and Activate Segment Anything tool again."; case mitk::SegmentAnythingPythonService::Status::KILLED: mitkThrow() << "Error: Python process is already terminated. Cannot load requested segmentation. Activate Segment Anything tool again."; default: return false; } } void mitk::SegmentAnythingPythonService::CreateTempDirs(const std::string &dirPattern) { this->SetMitkTempDir(IOUtil::CreateTemporaryDirectory(dirPattern)); m_InDir = IOUtil::CreateTemporaryDirectory("sam-in-XXXXXX", m_MitkTempDir); m_OutDir = IOUtil::CreateTemporaryDirectory("sam-out-XXXXXX", m_MitkTempDir); } mitk::LabelSetImage::Pointer mitk::SegmentAnythingPythonService::RetrieveImageFromProcess(long timeOut) { std::string outputImagePath = m_OutDir + IOUtil::GetDirectorySeparator() + m_CurrentUId + ".nrrd"; auto start = sys_clock::now(); while (!std::filesystem::exists(outputImagePath)) { this->CheckStatus(); std::this_thread::sleep_for(100ms); if (timeOut != -1 && std::chrono::duration_cast(sys_clock::now() - start).count() > timeOut) { CurrentStatus = Status::OFF; m_DaemonExec->SetStop(true); mitkThrow() << SIGNALCONSTANTS::TIMEOUT_ERROR; } } LabelSetImage::Pointer outputBuffer = mitk::IOUtil::Load(outputImagePath); return outputBuffer; } void mitk::SegmentAnythingPythonService::TransferImageToProcess(const Image *inputAtTimeStep, std::string &UId) { std::string inputImagePath = m_InDir + IOUtil::GetDirectorySeparator() + UId + ".nrrd"; if (inputAtTimeStep->GetPixelType().GetNumberOfComponents() < 2) { AccessByItk_n(inputAtTimeStep, ITKWriter, (inputImagePath)); } else { mitk::IOUtil::Save(inputAtTimeStep, inputImagePath); } m_CurrentUId = UId; } template void mitk::SegmentAnythingPythonService::ITKWriter(const itk::Image *image, std::string& outputFilename) { typedef itk::Image ImageType; typedef itk::ImageFileWriter WriterType; typename WriterType::Pointer writer = WriterType::New(); mitk::LocaleSwitch localeSwitch("C"); writer->SetFileName(outputFilename); writer->SetInput(image); try { writer->Update(); } catch (const itk::ExceptionObject &error) { MITK_ERROR << "Error: " << error << std::endl; mitkThrow() << "Error: " << error; } } diff --git a/Modules/SegmentationUI/Qmitk/QmitkMedSAMToolGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkMedSAMToolGUI.cpp index abd084f783..e587c68c92 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkMedSAMToolGUI.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkMedSAMToolGUI.cpp @@ -1,280 +1,279 @@ /*============================================================================ 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 "QmitkMedSAMToolGUI.h" #include -#include #include #include #include #include MITK_TOOL_GUI_MACRO(MITKSEGMENTATIONUI_EXPORT, QmitkMedSAMToolGUI, "") namespace { mitk::IPreferences *GetPreferences() { auto *preferencesService = mitk::CoreServices::GetPreferencesService(); return preferencesService->GetSystemPreferences()->Node("org.mitk.views.segmentation"); } -} // namespace +} QmitkMedSAMToolGUI::QmitkMedSAMToolGUI() : QmitkSegWithPreviewToolGUIBase(true) { m_EnableConfirmSegBtnFnc = [this](bool enabled) { bool result = false; auto tool = this->GetConnectedToolAs(); if (nullptr != tool) { result = enabled && tool->HasPicks(); } return result; }; m_Preferences = GetPreferences(); m_Preferences->OnPropertyChanged += mitk::MessageDelegate1( this, &QmitkMedSAMToolGUI::OnPreferenceChangedEvent); } QmitkMedSAMToolGUI::~QmitkMedSAMToolGUI() { auto tool = this->GetConnectedToolAs(); // check -ashis if (nullptr != tool) { tool->SAMStatusMessageEvent -= mitk::MessageDelegate1(this, &QmitkMedSAMToolGUI::StatusMessageListener); } } void QmitkMedSAMToolGUI::EnableAll(bool isEnable) { m_Controls.activateButton->setEnabled(isEnable); } void QmitkMedSAMToolGUI::WriteStatusMessage(const QString &message) { m_Controls.statusLabel->setText(message); m_Controls.statusLabel->setStyleSheet("font-weight: bold; color: white"); qApp->processEvents(); } void QmitkMedSAMToolGUI::WriteErrorMessage(const QString &message) { m_Controls.statusLabel->setText(message); m_Controls.statusLabel->setStyleSheet("font-weight: bold; color: red"); qApp->processEvents(); } void QmitkMedSAMToolGUI::ShowProgressBar(bool enabled) { m_Controls.samProgressBar->setEnabled(enabled); m_Controls.samProgressBar->setVisible(enabled); } void QmitkMedSAMToolGUI::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 QmitkMedSAMToolGUI::InitializeUI(QBoxLayout *mainLayout) { m_Controls.setupUi(this); m_Controls.statusLabel->setTextFormat(Qt::RichText); QString welcomeText; if (m_GpuLoader.GetGPUCount() != 0) { welcomeText = "STATUS: Welcome to MedSAM Anything tool. You're in luck: " + QString::number(m_GpuLoader.GetGPUCount()) + " GPU(s) were detected."; } else { welcomeText = "STATUS: Welcome to MedSAM Anything tool. Sorry, " + QString::number(m_GpuLoader.GetGPUCount()) + " GPUs were detected."; } connect(m_Controls.previewButton, SIGNAL(clicked()), this, SLOT(OnPreviewBtnClicked())); connect(m_Controls.activateButton, SIGNAL(clicked()), this, SLOT(OnActivateBtnClicked())); connect(m_Controls.resetButton, SIGNAL(clicked()), this, SLOT(OnResetPicksClicked())); QIcon arrowIcon = QmitkStyleManager::ThemeIcon( QStringLiteral(":/org_mitk_icons/icons/tango/scalable/actions/media-playback-start.svg")); m_Controls.activateButton->setIcon(arrowIcon); bool isInstalled = this->ValidatePrefences(); if (isInstalled) { QString modelType = QString::fromStdString(m_Preferences->Get("sam modeltype", "")); welcomeText += " MedSAM is already found installed."; } else { welcomeText += " MedSAM tool is not configured correctly. Please go to Preferences (Cntl+P) > Segment Anything to " "configure and/or install SAM & MedSAM."; } this->EnableAll(isInstalled); this->WriteStatusMessage(welcomeText); this->ShowProgressBar(false); m_Controls.samProgressBar->setMaximum(0); mainLayout->addLayout(m_Controls.verticalLayout); Superclass::InitializeUI(mainLayout); } bool QmitkMedSAMToolGUI::ValidatePrefences() { const QString storageDir = QString::fromStdString(m_Preferences->Get("sam python path", "")); bool isInstalled = QmitkSegmentAnythingToolGUI::IsSAMInstalled(storageDir); std::string modelType = m_Preferences->Get("sam modeltype", ""); std::string path = m_Preferences->Get("sam parent path", ""); return (isInstalled && !modelType.empty() && !path.empty()); } void QmitkMedSAMToolGUI::StatusMessageListener(const std::string &message) { if (message.rfind("Error", 0) == 0) { this->EnableAll(true); this->WriteErrorMessage(QString::fromStdString(message)); } else if (message == "TimeOut") { // trying to re init the daemon this->WriteErrorMessage(QString("STATUS: Sorry, operation timed out. Reactivating SAM tool...")); if (this->ActivateSAMDaemon()) { this->WriteStatusMessage(QString("STATUS: Segment Anything tool re-initialized.")); } else { this->WriteErrorMessage(QString("STATUS: Couldn't init tool backend.")); this->EnableAll(true); } } else { this->WriteStatusMessage(QString::fromStdString(message)); } } bool QmitkMedSAMToolGUI::ActivateSAMDaemon() { auto tool = this->GetConnectedToolAs(); if (nullptr == tool) { return false; } this->ShowProgressBar(true); qApp->processEvents(); try { tool->InitSAMPythonProcess(); while (!tool->IsPythonReady()) { qApp->processEvents(); } tool->IsReadyOn(); } catch (...) { tool->IsReadyOff(); } this->ShowProgressBar(false); return tool->GetIsReady(); } void QmitkMedSAMToolGUI::OnActivateBtnClicked() { auto tool = this->GetConnectedToolAs(); if (nullptr == tool) { return; } try { this->EnableAll(false); qApp->processEvents(); QString pythonPath = QString::fromStdString(m_Preferences->Get("sam python path", "")); if (!QmitkSegmentAnythingToolGUI::IsSAMInstalled(pythonPath)) { throw std::runtime_error(WARNING_SAM_NOT_FOUND); } tool->SetPythonPath(pythonPath.toStdString()); tool->SetGpuId(m_Preferences->GetInt("sam gpuid", -1)); tool->SetModelType("vit_b"); // MedSAM only works with vit_b tool->SetTimeOutLimit(m_Preferences->GetInt("sam timeout", 300)); tool->SetCheckpointPath(m_Preferences->Get("sam parent path", "")); tool->SetBackend("MedSAM"); this->WriteStatusMessage(QString("STATUS: Initializing MedSAM...")); tool->SAMStatusMessageEvent += mitk::MessageDelegate1(this, &QmitkMedSAMToolGUI::StatusMessageListener); if (this->ActivateSAMDaemon()) { this->WriteStatusMessage(QString("STATUS: MedSAM tool initialized.")); } else { this->WriteErrorMessage(QString("STATUS: Couldn't init tool backend.")); this->EnableAll(true); } } catch (const std::exception &e) { std::stringstream errorMsg; errorMsg << "STATUS: Error while processing parameters for MedSAM segmentation. Reason: " << e.what(); this->ShowErrorMessage(errorMsg.str()); this->WriteErrorMessage(QString::fromStdString(errorMsg.str())); this->EnableAll(true); return; } catch (...) { std::string errorMsg = "Unkown error occured while generation MedSAM segmentation."; this->ShowErrorMessage(errorMsg); this->EnableAll(true); return; } } void QmitkMedSAMToolGUI::OnPreviewBtnClicked() { auto tool = this->GetConnectedToolAs(); if (nullptr != tool) { tool->UpdatePreview(); } } void QmitkMedSAMToolGUI::OnResetPicksClicked() { auto tool = this->GetConnectedToolAs(); if (nullptr != tool) { tool->ClearPicks(); } } void QmitkMedSAMToolGUI::OnPreferenceChangedEvent(const mitk::IPreferences::ChangeEvent &) { this->EnableAll(true); this->WriteStatusMessage("A Preference change was detected. Please initialize the tool again."); auto tool = this->GetConnectedToolAs(); if (nullptr != tool) { tool->IsReadyOff(); } }