diff --git a/Modules/Segmentation/Interactions/mitkMonaiLabelTool.cpp b/Modules/Segmentation/Interactions/mitkMonaiLabelTool.cpp index 2fb6b0437b..97431db60c 100644 --- a/Modules/Segmentation/Interactions/mitkMonaiLabelTool.cpp +++ b/Modules/Segmentation/Interactions/mitkMonaiLabelTool.cpp @@ -1,391 +1,377 @@ /*============================================================================ 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. ============================================================================*/ // MITK #include "mitkMonaiLabelTool.h" // us #include "mitkIOUtil.h" -#include "mitkRESTUtil.h" +#include +#include #include #include #include #include #include #include #include #include -#include "cpprest/asyncrt_utils.h" -#include "cpprest/http_client.h" -#include - namespace mitk { MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, MonaiLabelTool, "MonaiLabel"); } mitk::MonaiLabelTool::MonaiLabelTool() { - InitializeRESTManager(); + this->SetMitkTempDir(IOUtil::CreateTemporaryDirectory("mitk-XXXXXX")); +} + +mitk::MonaiLabelTool::~MonaiLabelTool() +{ + itksys::SystemTools::RemoveADirectory(this->GetMitkTempDir()); } void mitk::MonaiLabelTool::Activated() { Superclass::Activated(); this->SetLabelTransferMode(LabelTransferMode::AllLabels); } const char **mitk::MonaiLabelTool::GetXPM() const { return nullptr; } us::ModuleResource mitk::MonaiLabelTool::GetIconResource() const { us::Module *module = us::GetModuleContext()->GetModule(); - us::ModuleResource resource = module->GetResource("Otsu_48x48.png"); + us::ModuleResource resource = module->GetResource("AI.svg"); return resource; } const char *mitk::MonaiLabelTool::GetName() const { return "MonaiLabel"; } +bool mitk::MonaiLabelTool::IsMonaiServerOn(std::string &hostName, int &port) +{ + httplib::Client cli(hostName, port); + while (cli.is_socket_open()); + if (auto response = cli.Get("/info/")) + { + return true; + } + return false; +} + void mitk::MonaiLabelTool::DoUpdatePreview(const Image *inputAtTimeStep, const Image * /*oldSegAtTimeStep*/, LabelSetImage *previewImage, TimeStepType timeStep) { - std::string outputImagePath = "Z:/dataset/Task05_Prostate/labelsTr/prostate_00.nii.gz"; + std::string &hostName = m_RequestParameters->hostName; + int port = m_RequestParameters->port; + if (!IsMonaiServerOn(hostName, port)) + { + mitkThrow() << m_SERVER_503_ERROR_TEXT; + } + std::string inDir, outDir, inputImagePath, outputImagePath; + inDir = IOUtil::CreateTemporaryDirectory("monai-in-XXXXXX", this->GetMitkTempDir()); + std::ofstream tmpStream; + inputImagePath = IOUtil::CreateTemporaryFile(tmpStream, m_TEMPLATE_FILENAME, inDir + IOUtil::GetDirectorySeparator()); + tmpStream.close(); + std::size_t found = inputImagePath.find_last_of(IOUtil::GetDirectorySeparator()); + std::string fileName = inputImagePath.substr(found + 1); + std::string token = fileName.substr(0, fileName.find("_")); + outDir = IOUtil::CreateTemporaryDirectory("monai-out-XXXXXX", this->GetMitkTempDir()); + outputImagePath = outDir + IOUtil::GetDirectorySeparator() + token + "_000.nii.gz"; + + try { + if (!m_TEST) + { + IOUtil::Save(inputAtTimeStep, inputImagePath); + PostInferRequest(hostName, port, inputImagePath, outputImagePath); + } + else + { + std::string metaData_test = + "{\"label_names\":{\"spleen\": 1, \"right kidney\": 2, \"left kidney\": 3, \"liver\": 6, \"stomach\": 7, " + "\"aorta\": 8, \"inferior " + "vena cava\": 9, \"background\": 0}, \"latencies\": {\"pre\": 0.64, \"infer\": 1.13, \"invert\": 0.03, " + "\"post\": 0.06, \"write\": 0.1, \"total\": 1.96, \"transform\": {\"pre\": {\"LoadImaged\": 0.1483, " + "\"EnsureChannelFirstd\": 0.0, \"Orientationd\": 0.0, \"ScaleIntensityRanged\": 0.0403, \"Resized\": 0.0401, " + "\"DiscardAddGuidanced\": 0.0297, \"EnsureTyped\": 0.3703}, \"post\": {\"EnsureTyped\": 0.0, \"Activationsd\": " + "0.0, \"AsDiscreted\": 0.0, \"SqueezeDimd\": 0.0, \"ToNumpyd\": 0.0473, \"Restored\": 0.0001}}}}"; + m_ResultMetadata = nlohmann::json::parse(metaData_test); + outputImagePath = "C:/DKFZ/MONAI_work/monai_test_python/output.nii.gz"; + } + Image::Pointer outputImage = IOUtil::Load(outputImagePath); - previewImage->InitializeByLabeledImage(outputImage); - previewImage->SetGeometry(inputAtTimeStep->GetGeometry()); + auto m_OutputBuffer = mitk::LabelSetImage::New(); + m_OutputBuffer->InitializeByLabeledImage(outputImage); + m_OutputBuffer->SetGeometry(inputAtTimeStep->GetGeometry()); + MITK_INFO << m_OutputBuffer->GetNumberOfLabels(); + + std::map labelMap = m_ResultMetadata["label_names"]; + std::map flippedLabelMap; + + for (auto const &[key, val] : labelMap) + { + flippedLabelMap[val] = key; + } + int labelId = 0; + for (auto const &[key, val] : flippedLabelMap) + { + mitk::Label *labelptr = m_OutputBuffer->GetLabel(labelId, 0); + if (nullptr != labelptr) + { + MITK_INFO << "Replacing label with name: " << labelptr->GetName() << " as " << val; + labelptr->SetName(val); + } + else + { + MITK_INFO << "nullptr found for " << val; + } + labelId++; + } + TransferLabelSetImageContent(m_OutputBuffer, previewImage, timeStep); } catch (const mitk::Exception &e) { - /* - Can't throw mitk exception to the caller. Refer: T28691 - */ MITK_ERROR << e.GetDescription(); - return; + mitkThrow() << e.GetDescription(); } } -void mitk::MonaiLabelTool::InitializeRESTManager() // Don't call from constructor --ashis +void mitk::MonaiLabelTool::GetOverallInfo(std::string &hostName, int &port) { - auto serviceRef = us::GetModuleContext()->GetServiceReference(); - if (serviceRef) + MITK_INFO << "URL..." << hostName << ":" << port; + if (!IsMonaiServerOn(hostName, port)) { - m_RESTManager = us::GetModuleContext()->GetService(serviceRef); + Tool::ErrorMessage.Send(m_SERVER_503_ERROR_TEXT); + mitkThrow() << m_SERVER_503_ERROR_TEXT; } -} - -void mitk::MonaiLabelTool::GetOverallInfo(std::string url) -{ - MITK_INFO << "URL..." << url; - httplib::Client cli("localhost", 8000); - auto response = cli.Get("/info/"); - if (response->status == 200) + httplib::Client cli(hostName, port); // httplib::Client cli("localhost", 8000); + if (auto response = cli.Get("/info/")) { - auto jsonObj = nlohmann::json::parse(response->body); - if (jsonObj.is_discarded() || !jsonObj.is_object()) + if (response->status == 200) { - MITK_ERROR << "Could not parse \"" << /* jsonPath.toStdString() << */ "\" as JSON object!"; - return; + auto jsonObj = nlohmann::json::parse(response->body); + if (jsonObj.is_discarded() || !jsonObj.is_object()) + { + MITK_ERROR << "Could not parse \"" << /* jsonPath.toStdString() << */ "\" as JSON object!"; + return; + } + m_InfoParameters = DataMapper(jsonObj); + if (nullptr != m_InfoParameters) + { + m_InfoParameters->hostName = hostName; + m_InfoParameters->port = port; + } } - m_Parameters = DataMapper(jsonObj); } - - //if (m_RESTManager != nullptr) - //{ - // //PostSegmentationRequest(); - // std::string jsonString; - // bool fetched = false; - // web::json::value result; - // m_RESTManager->SendRequest(mitk::RESTUtil::convertToTString(url)) - // .then( - // [&](pplx::task resultTask) /*It is important to use task-based continuation*/ - // { - // try - // { - // result = resultTask.get(); - // fetched = true; - // } - // catch (const mitk::Exception &exception) - // { - // MITK_ERROR << exception.what(); - // return; - // } - // }) - // .wait(); - /* if (fetched) - { - m_Parameters = DataMapper(result); - }*/ - //} + else + { + Tool::ErrorMessage.Send(httplib::to_string(response.error())+" error occured."); + } } -void mitk::MonaiLabelTool::PostSegmentationRequest() +void mitk::MonaiLabelTool::PostInferRequest(std::string &hostName, + int &port, + std::string &filePath, + std::string &outFile) { - std::string url = "http://localhost:8000/infer/deepedit_seg"; // + m_ModelName; - // std::string filePath = "//vmware-host//Shared Folders//Downloads//spleen_58.nii.gz"; - std::string filePath = "C://data//dataset//Task02_Heart//imagesTr//la_016.nii.gz"; + // std::string url = "http://localhost:8000/infer/deepedit_seg"; // + m_ModelName; + std::string &modelName = m_RequestParameters->model.name; // Get this from args as well. + std::string postPath = "/infer/"; // make this separate class of constants + postPath.append(modelName); + + // std::string filePath = "C:/DKFZ/MONAI_work/monai_test_python/la_030.nii.gz"; std::ifstream input(filePath, std::ios::binary); if (!input) { MITK_WARN << "could not read file to POST"; } std::stringstream buffer_lf_img; buffer_lf_img << input.rdbuf(); - httplib::Client cli("localhost", 8000); + input.close(); httplib::MultipartFormDataItems items = { - {"file", buffer_lf_img.str(), "spleen_58.nii.gz", "application/octet-stream"}}; - - // httplib::MultipartFormDataMap itemMap = {{"file", {"file", buffer_lf_img.str(), "spleen_58.nii.gz", - // "application/octet-stream"}}}; - - auto response = cli.Post("/infer/deepedit_seg", items); - if (response->status == 200) - { - MITK_INFO<body; - auto h = response->headers; - std::string contentType = h.find("content-type")->second; - std::string delimiter = "boundary="; - std::string boundaryString = contentType.substr(contentType.find(delimiter)+delimiter.length(), std::string::npos); - boundaryString.insert(0, "--"); - MITK_INFO << "boundary hash: " << boundaryString; - - std::string resBody = response->body; - resBody.erase(0, boundaryString.length()); - std::string metaData = resBody.substr(0, resBody.find(boundaryString)); - MITK_INFO << metaData; - auto jsonObj = nlohmann::json::parse(metaData); - if (jsonObj.is_discarded() || !jsonObj.is_object()) + {"file", buffer_lf_img.str(), "post_from_mitk.nii.gz", "application/octet-stream"}}; + // httplib::MultipartFormDataMap itemMap = {{"file", {"file", buffer_lf_img.str(), "spleen_58.nii.gz", "application/octet-stream"}}}; + + httplib::Client cli(hostName, port); + cli.set_read_timeout(60); + if (auto response = cli.Post(postPath, items)) //auto response = cli.Post("/infer/deepedit_seg", items); + { + if (response->status == 200) { - MITK_ERROR << "Could not parse \"" << /* jsonPath.toStdString() << */ "\" as JSON object!"; - return; + // Find boundary + httplib::Headers headers = response->headers; + std::string contentType = headers.find("content-type")->second; + std::string delimiter = "boundary="; + std::string boundaryString = + contentType.substr(contentType.find(delimiter) + delimiter.length(), std::string::npos); + boundaryString.insert(0, "--"); + MITK_INFO << "boundary hash: " << boundaryString; + + // Parse metadata JSON + std::string resBody = response->body; + std::vector multiPartResponse = this->getPartsBetweenBoundary(resBody, boundaryString); + + std::string metaData = multiPartResponse[0]; + std::string contentTypeJson = "Content-Type: application/json"; + size_t ctPos = metaData.find(contentTypeJson) + contentTypeJson.length(); + std::string metaDataPart = metaData.substr(ctPos); + MITK_INFO << metaDataPart; + auto jsonObj = nlohmann::json::parse(metaDataPart); + if (jsonObj.is_discarded() || !jsonObj.is_object()) + { + MITK_ERROR << "Could not parse \"" << /* jsonPath.toStdString() << */ "\" as JSON object!"; + return; + } + else // use the metadata + { + m_ResultMetadata = jsonObj; + } + // Parse response image string + std::string imagePart = multiPartResponse[1]; + std::string contentTypeStream = "Content-Type: application/octet-stream"; + ctPos = imagePart.find(contentTypeStream) + contentTypeStream.length(); + std::string imageDataPart = imagePart.substr(ctPos); + + MITK_INFO << imageDataPart.substr(0, 50); + std::string whitespaces = " \n\r"; + imageDataPart.erase(0, imageDataPart.find_first_not_of(whitespaces)); // clean up + std::ofstream output(outFile, std::ios::out | std::ios::app | std::ios::binary); + output << imageDataPart; + output.unsetf(std::ios::skipws); + output.flush(); + output.close(); // necessary to close? RAII + } + else + { + auto err = response.error(); + MITK_ERROR << "An HTTP POST error: " << httplib::to_string(err) << " occured."; + mitkThrow() << "An HTTP POST error: " << httplib::to_string(err) << " occured."; } } } - -std::unique_ptr mitk::MonaiLabelTool::DataMapper(nlohmann::json &jsonObj) +std::vector mitk::MonaiLabelTool::getPartsBetweenBoundary(const std::string &body, + const std::string &boundary) { - auto object = std::make_unique(); - object->name = jsonObj["name"].get(); - object->description = jsonObj["description"].get(); - object->labels = jsonObj["labels"].get>(); - - auto modelJsonMap = jsonObj["models"].get>(); - for (const auto &[_name, _jsonObj] : modelJsonMap) + std::vector retVal; + std::string master = body; + size_t found = master.find(boundary); + size_t beginPos = 0; + while (found != std::string::npos) { - if (_jsonObj.is_discarded() || !_jsonObj.is_object()) + std::string part = master.substr(beginPos, found); + if (!part.empty()) { - MITK_ERROR << "Could not parse JSON object."; + retVal.push_back(part); } - MonaiModelInfo modelInfo; - modelInfo.name = _name; - try - { - auto labels = _jsonObj["labels"].get>(); - modelInfo.labels = labels; - } - catch (const std::exception &) - { - auto labels = _jsonObj["labels"].get>(); - for (const auto &label : labels) - { - modelInfo.labels[label] = -1; // Hardcode -1 as label id - } - } - modelInfo.type = _jsonObj["type"].get(); - modelInfo.dimension = _jsonObj["dimension"].get(); - modelInfo.description = _jsonObj["description"].get(); - - object->models.push_back(modelInfo); + master.erase(beginPos, found + boundary.length()); + found = master.find(boundary); } - return object; + return retVal; } - -std::unique_ptr mitk::MonaiLabelTool::DataMapper(web::json::value &result) +std::unique_ptr mitk::MonaiLabelTool::DataMapper(nlohmann::json &jsonObj) { auto object = std::make_unique(); - utility::string_t stringT = result.to_string(); - std::string jsonString(stringT.begin(), stringT.end()); - auto jsonObj = nlohmann::json::parse(jsonString); - if (jsonObj.is_discarded() || !jsonObj.is_object()) - { - MITK_ERROR << "Could not parse \"" << jsonString << "\" as JSON object!"; - } - //MITK_INFO << jsonString; - MITK_INFO << "ashis inside mapper " << jsonObj["name"].get(); // remove object->name = jsonObj["name"].get(); object->description = jsonObj["description"].get(); object->labels = jsonObj["labels"].get>(); auto modelJsonMap = jsonObj["models"].get>(); for (const auto &[_name, _jsonObj] : modelJsonMap) { if (_jsonObj.is_discarded() || !_jsonObj.is_object()) { MITK_ERROR << "Could not parse JSON object."; } MonaiModelInfo modelInfo; modelInfo.name = _name; try { auto labels = _jsonObj["labels"].get>(); modelInfo.labels = labels; } catch (const std::exception &) { auto labels = _jsonObj["labels"].get>(); for (const auto &label : labels) { modelInfo.labels[label] = -1; // Hardcode -1 as label id } } modelInfo.type = _jsonObj["type"].get(); modelInfo.dimension = _jsonObj["dimension"].get(); modelInfo.description = _jsonObj["description"].get(); object->models.push_back(modelInfo); } return object; } - -std::vector mitk::MonaiLabelTool::GetAutoSegmentationModels() +std::vector mitk::MonaiLabelTool::GetAutoSegmentationModels() { std::vector autoModels; - if (nullptr != m_Parameters) + if (nullptr != m_InfoParameters) { - for (mitk::MonaiModelInfo &model : m_Parameters->models) + for (mitk::MonaiModelInfo &model : m_InfoParameters->models) { if (m_AUTO_SEG_TYPE_NAME.find(model.type) != m_AUTO_SEG_TYPE_NAME.end()) { autoModels.push_back(model); } } } return autoModels; } std::vector mitk::MonaiLabelTool::GetInteractiveSegmentationModels() { std::vector interactiveModels; - if (nullptr != m_Parameters) + if (nullptr != m_InfoParameters) { - for (mitk::MonaiModelInfo &model : m_Parameters->models) + for (mitk::MonaiModelInfo &model : m_InfoParameters->models) { if (m_INTERACTIVE_SEG_TYPE_NAME.find(model.type) != m_INTERACTIVE_SEG_TYPE_NAME.end()) { interactiveModels.push_back(model); } } } return interactiveModels; } std::vector mitk::MonaiLabelTool::GetScribbleSegmentationModels() { std::vector scribbleModels; - if (nullptr != m_Parameters) + if (nullptr != m_InfoParameters) { - for (mitk::MonaiModelInfo &model : m_Parameters->models) + for (mitk::MonaiModelInfo &model : m_InfoParameters->models) { if (m_SCRIBBLE_SEG_TYPE_NAME.find(model.type) != m_SCRIBBLE_SEG_TYPE_NAME.end()) { scribbleModels.push_back(model); } } } return scribbleModels; } - -//void mitk::MonaiLabelTool::PostSegmentationRequest() // return LabelSetImage ?? -//{ -// // web::json::value result; -// // web::json::value data; -// -// std::string url = "http://localhost:8000/infer/deepedit_seg"; // + m_ModelName; -// std::string filePath = "//vmware-host//Shared Folders//Downloads//spleen_58.nii.gz"; -// std::ifstream input(filePath, std::ios::binary); -// if (!input) -// { -// MITK_WARN << "could not read file to POST"; -// } -// -// std::vector result; -// std::vector buffer; -// -// // Stop eating new lines in binary mode!!! -// input.unsetf(std::ios::skipws); -// -// input.seekg(0, std::ios::end); -// const std::streampos fileSize = input.tellg(); -// input.seekg(0, std::ios::beg); -// -// MITK_INFO << fileSize << " bytes will be sent."; -// buffer.reserve(fileSize); // file size -// std::copy( -// std::istream_iterator(input), std::istream_iterator(), std::back_inserter(buffer)); -// -// -// mitk::RESTUtil::ParamMap headers; -// headers.insert(mitk::RESTUtil::ParamMap::value_type(U("accept"), U("application/json"))); -// // headers.insert(mitk::RESTUtil::ParamMap::value_type(U("Accept-Encoding"), U("gzip, deflate"))); -// headers.insert(mitk::RESTUtil::ParamMap::value_type( -// // U("Content-Type"), U("multipart/related; type=\"application/dicom\"; boundary=boundary"))); -// U("Content-Type"), U("multipart/form-data; boundary=boundary"))); -// -// // in future more than one file should also be supported.. -// std::string head = ""; -// head += "\r\n--boundary"; -// head += "\r\nContent-Disposition: form-data; name=\"params\"\r\n\r\n{}"; -// head += "\r\n--boundary"; -// head += "\r\nContent-Disposition: form-data; name=\"file\"; filename=\"spleen_58.nii.gz\"\r\n\r\n"; -// -// std::vector bodyVector(head.begin(), head.end()); -// -// std::string tail = ""; -// tail += "\r\n--boundary"; -// tail += "\r\nContent-Disposition: form-data; name=\"label\"\r\n\r\n"; -// tail += "\r\n--boundary--\r\n"; -// -// result.insert(result.end(), bodyVector.begin(), bodyVector.end()); -// result.insert(result.end(), buffer.begin(), buffer.end()); -// result.insert(result.end(), tail.begin(), tail.end()); -// -// try -// { -// m_RESTManager -// ->SendBinaryRequest(mitk::RESTUtil::convertToTString(url), mitk::IRESTManager::RequestType::Post, &result, headers) -// .then( -// [=](pplx::task result) /* (web::json::value result)*/ -// { -// MITK_INFO << "after send"; -// //MITK_INFO << mitk::RESTUtil::convertToUtf8(result.serialize()); -// //result.is_null(); -// }) -// .wait(); -// } -// catch (std::exception &e) -// { -// MITK_WARN << e.what(); -// } -//} \ No newline at end of file diff --git a/Modules/Segmentation/Interactions/mitkMonaiLabelTool.h b/Modules/Segmentation/Interactions/mitkMonaiLabelTool.h index a850ae13b9..3847eef8fb 100644 --- a/Modules/Segmentation/Interactions/mitkMonaiLabelTool.h +++ b/Modules/Segmentation/Interactions/mitkMonaiLabelTool.h @@ -1,102 +1,110 @@ /*============================================================================ 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 MITKMONAILABELTOOL_H #define MITKMONAILABELTOOL_H #include "mitkSegWithPreviewTool.h" #include -#include #include #include #include #include #include namespace us { class ModuleResource; } namespace mitk { - // class Image; - struct MonaiModelInfo { std::string name; std::string type; std::unordered_map labels; int dimension; std::string description; std::unordered_map config; //TODO: find the full extent }; struct MonaiAppMetadata { - std::string URL; - unsigned short port; + std::string hostName; + int port; std::string origin; std::string name; std::string description; std::string version; std::vector labels; std::vector models; }; + struct MonaiLabelRequest + { + /*Parameters that goes into infer POST*/ + MonaiModelInfo model; + std::string hostName; + int port; + }; + + class MITKSEGMENTATION_EXPORT MonaiLabelTool : public SegWithPreviewTool { public: mitkClassMacro(MonaiLabelTool, SegWithPreviewTool); itkFactorylessNewMacro(Self); itkCloneMacro(Self); + bool m_TEST = false; // cleanup later const char *GetName() const override; const char **GetXPM() const override; us::ModuleResource GetIconResource() const override; void Activated() override; - void GetOverallInfo(std::string); - std::unique_ptr m_Parameters; //contains all parameters from Server to serve the GUI + void GetOverallInfo(std::string&, int&); + std::unique_ptr m_InfoParameters; //contains all parameters from Server to serve the GUI + std::unique_ptr m_RequestParameters; std::vector GetAutoSegmentationModels(); std::vector GetInteractiveSegmentationModels(); std::vector GetScribbleSegmentationModels(); - void PostSegmentationRequest(); + void PostInferRequest(std::string &, int &, std::string &, std::string &); itkSetMacro(ModelName, std::string); itkGetConstMacro(ModelName, std::string); itkSetMacro(URL, std::string); itkGetConstMacro(URL, std::string); - - + itkSetMacro(MitkTempDir, std::string); + itkGetConstMacro(MitkTempDir, std::string); protected: MonaiLabelTool(); - ~MonaiLabelTool() = default; - + ~MonaiLabelTool(); void DoUpdatePreview(const Image* inputAtTimeStep, const Image* oldSegAtTimeStep, LabelSetImage* previewImage, TimeStepType timeStep) override; - private: - void InitializeRESTManager(); - std::unique_ptr DataMapper(web::json::value&); + std::string m_MitkTempDir; + std::vector getPartsBetweenBoundary(const std::string &, const std::string &); std::unique_ptr mitk::MonaiLabelTool::DataMapper(nlohmann::json&); - mitk::IRESTManager *m_RESTManager; + bool IsMonaiServerOn(std::string &, int &); + std::string m_ModelName; + std::string m_URL; + nlohmann::json m_ResultMetadata; const std::set m_AUTO_SEG_TYPE_NAME = {"segmentation"}; const std::set m_SCRIBBLE_SEG_TYPE_NAME = {"scribbles"}; const std::set m_INTERACTIVE_SEG_TYPE_NAME = {"deepedit", "deepgrow"}; - std::string m_ModelName; - std::string m_URL; - + const std::string m_TEMPLATE_FILENAME = "XXXXXX_000_0000.nii.gz"; + const std::string m_SERVER_503_ERROR_TEXT = "A connection to MonaiLabel server cannot be established."; }; // class } // namespace #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUI.cpp index 40648c039f..092dd8f87e 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUI.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUI.cpp @@ -1,92 +1,147 @@ #include "QmitkMonaiLabelToolGUI.h" -#include "mitkMonaiLabelTool.h" -#include -#include -#include +#include "mitkMonaiLabelTool.h" #include "usServiceReference.h" #include #include #include - +#include +#include +#include MITK_TOOL_GUI_MACRO(MITKSEGMENTATIONUI_EXPORT, QmitkMonaiLabelToolGUI, "") QmitkMonaiLabelToolGUI::QmitkMonaiLabelToolGUI() : QmitkMultiLabelSegWithPreviewToolGUIBase(), m_SuperclassEnableConfirmSegBtnFnc(m_EnableConfirmSegBtnFnc) { m_EnableConfirmSegBtnFnc = [this](bool enabled) - { - return !m_FirstPreviewComputation ? m_SuperclassEnableConfirmSegBtnFnc(enabled) : false; - }; + { return !m_FirstPreviewComputation ? m_SuperclassEnableConfirmSegBtnFnc(enabled) : false; }; } -void QmitkMonaiLabelToolGUI::ConnectNewTool(mitk::SegWithPreviewTool* newTool) +void QmitkMonaiLabelToolGUI::ConnectNewTool(mitk::SegWithPreviewTool *newTool) { Superclass::ConnectNewTool(newTool); newTool->IsTimePointChangeAwareOff(); m_FirstPreviewComputation = true; } -void QmitkMonaiLabelToolGUI::InitializeUI(QBoxLayout* mainLayout) -{ +void QmitkMonaiLabelToolGUI::InitializeUI(QBoxLayout *mainLayout) +{ m_Controls.setupUi(this); mainLayout->addLayout(m_Controls.verticalLayout); connect(m_Controls.previewButton, SIGNAL(clicked()), this, SLOT(OnPreviewBtnClicked())); connect(m_Controls.fetchUrl, SIGNAL(clicked()), this, SLOT(OnFetchBtnClicked())); - QIcon refreshIcon = QmitkStyleManager::ThemeIcon(QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/actions/view-refresh.svg")); + QIcon refreshIcon = + QmitkStyleManager::ThemeIcon(QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/actions/view-refresh.svg")); m_Controls.fetchUrl->setIcon(refreshIcon); Superclass::InitializeUI(mainLayout); } void QmitkMonaiLabelToolGUI::EnableWidgets(bool enabled) { Superclass::EnableWidgets(enabled); } void QmitkMonaiLabelToolGUI::OnFetchBtnClicked() { auto tool = this->GetConnectedToolAs(); if (nullptr != tool) { + tool->m_InfoParameters.reset(); + m_Controls.modelBox->clear(); + m_Controls.appBox->clear(); QString urlString = m_Controls.urlBox->text(); QUrl url(urlString); if (url.isValid() && !url.isLocalFile() && !url.hasFragment() && !url.hasQuery()) // sanity check { - tool->GetOverallInfo(urlString.toStdString()); - // tool->GetOverallInfo("http://localhost:8000/info"); - if (nullptr != tool->m_Parameters) + QString hostName = url.host(); + int port = url.port(); + try { - std::string response = tool->m_Parameters->name; - std::vector autoModels = tool->GetAutoSegmentationModels(); - m_Controls.responseNote->setText(QString::fromStdString(response)); - m_Controls.appBox->addItem(QString::fromStdString(response)); - for (auto &model : autoModels) + tool->GetOverallInfo(hostName.toStdString(), port); + // tool->GetOverallInfo("localhost",8000"); + if (nullptr != tool->m_InfoParameters) { - m_Controls.modelBox->addItem(QString::fromStdString(model.name)); + std::string response = tool->m_InfoParameters->name; + std::vector autoModels = tool->GetAutoSegmentationModels(); + m_Controls.responseNote->setText(QString::fromStdString(response)); + m_Controls.appBox->addItem(QString::fromStdString(response)); + for (auto &model : autoModels) + { + m_Controls.modelBox->addItem(QString::fromStdString(model.name)); + } } } + catch (const mitk::Exception &e) + { + MITK_ERROR << e.GetDescription(); // Add GUI msg box to show + } } else { - MITK_ERROR << "Invalid URL entered: " << urlString.toStdString(); + MITK_ERROR << "Invalid URL entered: " << urlString.toStdString(); // set as status message on GUI } } } void QmitkMonaiLabelToolGUI::OnPreviewBtnClicked() { auto tool = this->GetConnectedToolAs(); if (nullptr != tool) { - /* QString url = m_Controls.url->text(); - MITK_INFO << "tool found" << url.toStdString();*/ + if (false) + { + std::string selectedModel = m_Controls.modelBox->currentText().toStdString(); + for (const mitk::MonaiModelInfo &modelObject : tool->m_InfoParameters->models) + { + if (modelObject.name == selectedModel) + { + tool->m_RequestParameters = std::make_unique(); + tool->m_RequestParameters->model = modelObject; + tool->m_RequestParameters->hostName = tool->m_InfoParameters->hostName; + tool->m_RequestParameters->port = tool->m_InfoParameters->port; + MITK_INFO << "tool found" << selectedModel; + break; + } + } + } + else + { + MITK_INFO << " RUNNING ON TEST parameters..."; + tool->m_RequestParameters = std::make_unique(); + mitk::MonaiModelInfo modelObject; + modelObject.name = "deepedit_seg"; + tool->m_RequestParameters->model = modelObject; + tool->m_RequestParameters->hostName = "localhost"; + tool->m_RequestParameters->port = 8000; + } + try + { + tool->UpdatePreview(); + } + catch (const mitk::Exception &e) + { + MITK_ERROR << "Connection error"; // Add GUI msg box to show + } + mitk::LabelSetImage *temp = tool->GetPreviewSegmentation(); + for (int i = 0; i < temp->GetNumberOfLabels(); ++i) + { + mitk::Label *labelptr = temp->GetLabel(i, 0); + if (nullptr != labelptr) + { + MITK_INFO << "Label with name: " << labelptr->GetName(); + } + else + { + MITK_INFO << "nullptr found for " << i; + } + } - //tool->GetOverallInfo("https://httpbin.org/get"); - tool->PostSegmentationRequest(); + this->SetLabelSetPreview(tool->GetPreviewSegmentation()); + tool->IsTimePointChangeAwareOn(); + this->ActualizePreviewLabelVisibility(); } - //tool->UpdatePreview(); } diff --git a/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUIControls.ui b/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUIControls.ui index 28d745d832..cc197b4d5a 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUIControls.ui +++ b/Modules/SegmentationUI/Qmitk/QmitkMonaiLabelToolGUIControls.ui @@ -1,186 +1,180 @@ - QmitkMonaiLabelToolGUIControls - - - - 0 - 0 - 699 - 352 - - - - - 0 - 0 - - - - - 100 - 0 - - - - - 100000 - 100000 - - - - QmitkMonaiToolWidget - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - 0 - 0 - - - - <html><head/><body><p>Welcome to MONAI Label App in MITK. [Experimental]</p><p>Please note that this is only an interface to MONAI Label. MITK does not ship with any apps. Make sure to have a started a MONAI Label server beforehand. Provide the URL in the URL path to start the workflow. </p><p>Refer to <a href="https://github.com/MIC-DKFZ/nnUNet"><span style=" text-decoration: underline; color:#0000ff;">https://docs.monai.io/projects/label/en/latest/</span></a> to learn everything about the MONAI Label App.</p><p><br/></p></body></html> - - - Qt::RichText - - - true - - - - - - - - - 0 - 0 - - - - Monai Server URL: - - - - - - - - - - - - - - - 0 - 0 - - - - Available Apps: - - - - - - - - - - - - 0 - 0 - - - - Models: - - - - - - - - - - - - - 0 - 0 - - - - <html><head/><body><p>Welcome to Monai Label in MITK. [Experimental] - - - Qt::RichText - - - true - - - - - - - - - - - 0 - 0 - - - - - 100000 - 16777215 - - - - Preview - - - - - - - - - ctkExpandButton - QToolButton -
ctkExpandButton.h
-
- - ctkComboBox - QComboBox -
ctkComboBox.h
- 1 -
-
- - + QmitkMonaiLabelToolGUIControls + + + + 0 + 0 + 699 + 352 + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100000 + 100000 + + + + QmitkMonaiToolWidget + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Welcome to Monai Label in MITK. [Experimental] + + + Qt::RichText + + + true + + + + + + + + 0 + 0 + + + + Monai Server URL: + + + + + + + http://localhost:8000 + + + + + + + + + + + 0 + 0 + + + + Available Apps: + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Welcome to MONAI Label App in MITK. [Experimental]</p><p>Please note that this is only an interface to MONAI Label. MITK does not ship with any apps. Make sure to have a started a MONAI Label server beforehand. </p><p>Refer to <a href="https://github.com/MIC-DKFZ/nnUNet"><span style=" text-decoration: underline; color:#0000ff;">https://docs.monai.io/projects/label/en/latest/</span></a> to learn everything about the MONAI Label App.</p><p>Provide a valid URL (eg. http://localhost:8000) to the server &amp; start the workflow. </p><p><br/></p></body></html> + + + Qt::RichText + + + true + + + + + + + + 0 + 0 + + + + Models: + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 100000 + 16777215 + + + + Preview + + + + + + + + + ctkComboBox + QComboBox +
ctkComboBox.h
+ 1 +
+
+ +
diff --git a/Modules/SegmentationUI/files.cmake b/Modules/SegmentationUI/files.cmake index 5ebb388773..a8d4dc9575 100644 --- a/Modules/SegmentationUI/files.cmake +++ b/Modules/SegmentationUI/files.cmake @@ -1,81 +1,82 @@ 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/QmitkMonaiLabelToolGUI.cpp Qmitk/QmitkSurfaceStampWidget.cpp Qmitk/QmitkMaskStampWidget.cpp Qmitk/QmitkStaticDynamicSegmentationDialog.cpp Qmitk/QmitkSurfaceBasedInterpolatorWidget.cpp Qmitk/QmitkSimpleLabelSetListWidget.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/QmitkMonaiLabelToolGUI.h Qmitk/QmitknnUNetEnsembleLayout.h Qmitk/QmitkSurfaceStampWidget.h Qmitk/QmitkMaskStampWidget.h Qmitk/QmitkStaticDynamicSegmentationDialog.h Qmitk/QmitkSurfaceBasedInterpolatorWidget.h Qmitk/QmitkSimpleLabelSetListWidget.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/QmitkMonaiLabelToolGUIControls.ui ) set(QRC_FILES resources/SegmentationUI.qrc )