diff --git a/Modules/REST/include/mitkIRESTManager.h b/Modules/REST/include/mitkIRESTManager.h index c2f71d4ef3..e09a2be31f 100644 --- a/Modules/REST/include/mitkIRESTManager.h +++ b/Modules/REST/include/mitkIRESTManager.h @@ -1,99 +1,100 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkIRESTManager_h #define mitkIRESTManager_h #include #include #include #include namespace mitk { class IRESTObserver; class RESTServer; /** * @class IRESTManager * @brief This is a microservice interface for managing REST requests. */ class MITKREST_EXPORT IRESTManager { public: virtual ~IRESTManager(); /** * @brief request type for client requests by calling SendRequest */ enum class RequestType { Get, Post, Put }; /** * @brief Executes a HTTP request in the mitkRESTClient class * * @param uri defines the URI the request is send to * @param type the RequestType of the HTTP request (optional) * @param body the body for the request (optional) * @return task to wait for */ virtual pplx::task SendRequest( const web::uri &uri, const RequestType &type = RequestType::Get, const web::json::value *body = nullptr, + const std::map headers = {}, const utility::string_t &filePath = {} ) = 0; /** * @brief starts listening for requests if there isn't another observer listening and the port is free * * @param uri defines the URI for which incoming requests should be send to the observer * @param observer the observer which handles the incoming requests */ virtual void ReceiveRequest(const web::uri &uri, IRESTObserver *observer) = 0; /** * @brief Handles incoming requests by notifying the observer which should receive it * * @param uri defines the URI of the request * @param body the body of the request * @return the data which is modified by the notified observer */ virtual web::json::value Handle(const web::uri &uri, const web::json::value &body) = 0; /** * @brief Handles the deletion of an observer for all or a specific uri * * @param observer the observer which shouldn't receive requests anymore * @param uri the uri for which the observer doesn't handle requests anymore (optional) */ virtual void HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri = {}) = 0; virtual const std::map& GetServerMap() = 0; virtual const std::map, IRESTObserver *>& GetObservers() = 0; }; } MITK_DECLARE_SERVICE_INTERFACE(mitk::IRESTManager, "org.mitk.IRESTManager") #endif diff --git a/Modules/REST/include/mitkRESTClient.h b/Modules/REST/include/mitkRESTClient.h index 0f52864d49..acf76f42c2 100644 --- a/Modules/REST/include/mitkRESTClient.h +++ b/Modules/REST/include/mitkRESTClient.h @@ -1,74 +1,78 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkRESTClient_h #define mitkRESTClient_h #include #include namespace mitk { class MITKREST_EXPORT RESTClient { public: RESTClient(); ~RESTClient(); /** * @brief Executes a HTTP GET request with the given uri and returns a task waiting for a json object * * @throw mitk::Exception if request went wrong * @param uri the URI resulting the target of the HTTP request + * @param the additional headers to be set to the HTTP request * @return task to wait for with resulting json object */ - pplx::task Get(const web::uri &uri); + pplx::task Get(const web::uri &uri, const std::map headers); /** * @brief Executes a HTTP GET request with the given uri and and stores the byte stream in a file given by the * filePath * * @throw mitk::Exception if request went wrong * @param uri the URI resulting the target of the HTTP request + * @param the additional headers to be set to the HTTP request * @return task to wait for returning an empty json object */ - pplx::task Get(const web::uri &uri, const utility::string_t &filePath); + pplx::task Get(const web::uri &uri, + const utility::string_t &filePath, + const std::map headers); /** * @brief Executes a HTTP PUT request with given uri and the content given as json * * @throw mitk::Exception if request went wrong * @param uri defines the URI resulting the target of the HTTP request * @param content the content as json value which should be the body of the request and thus the content of the * created resources * @return task to wait for with resulting json object */ pplx::task Put(const web::uri &uri, const web::json::value *content); /** * @brief Executes a HTTP POST request with given uri and the content given as json * * @throw mitk::Exception if request went wrong * @param uri defines the URI resulting the target of the HTTP request * @param content the content as json value which should be the body of the request and thus the content of the * created resource * @return task to wait for with resulting json object */ pplx::task Post(const web::uri &uri, const web::json::value *content); }; } #endif diff --git a/Modules/REST/include/mitkRESTUtil.h b/Modules/REST/include/mitkRESTUtil.h index 4abc640f96..70d6ce86c8 100644 --- a/Modules/REST/include/mitkRESTUtil.h +++ b/Modules/REST/include/mitkRESTUtil.h @@ -1,46 +1,49 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkRESTUtil_h #define mitkRESTUtil_h #include #include namespace mitk { class MITKREST_EXPORT RESTUtil { public: + + typedef std::map ParamMap; + /** * @brief Converts the given std::wstring into a std::string representation */ static std::string convertToUtf8(const utility::string_t &string) { return utility::conversions::to_utf8string(string); } /** * @brief Converts the given std::string into a std::wstring representation */ static utility::string_t convertToTString(const std::string &string) { return utility::conversions::to_string_t(string); } }; } #endif diff --git a/Modules/REST/src/mitkRESTClient.cpp b/Modules/REST/src/mitkRESTClient.cpp index e6e6f2e755..e2327e42ca 100644 --- a/Modules/REST/src/mitkRESTClient.cpp +++ b/Modules/REST/src/mitkRESTClient.cpp @@ -1,162 +1,175 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include using http_client = web::http::client::http_client; using http_request = web::http::http_request; using http_response = web::http::http_response; using methods = web::http::methods; using status_codes = web::http::status_codes; using file_buffer = concurrency::streams::file_buffer; using streambuf = concurrency::streams::streambuf; mitk::RESTClient::RESTClient() { } mitk::RESTClient::~RESTClient() { } -pplx::task mitk::RESTClient::Get(const web::uri &uri) +pplx::task mitk::RESTClient::Get(const web::uri &uri, + const std::map headers) { auto client = new http_client(uri); http_request request; + for (auto param : headers) + { + request.headers().add(param.first, param.second); + } + return client->request(request).then([=](pplx::task responseTask) { try { auto response = responseTask.get(); auto status = response.status_code(); if (status_codes::OK != status) mitkThrow(); auto requestContentType = response.headers().content_type(); if (_XPLATSTR("application/json") != requestContentType) response.headers().set_content_type(_XPLATSTR("application/json")); return response.extract_json().get(); } catch (...) { mitkThrow() << "Getting response went wrong"; } }); } -pplx::task mitk::RESTClient::Get(const web::uri &uri, const utility::string_t &filePath) +pplx::task mitk::RESTClient::Get(const web::uri &uri, + const utility::string_t &filePath, + const std::map headers) { auto client = new http_client(uri); auto fileBuffer = std::make_shared>(); http_request request; + for (auto param : headers) + { + request.headers().add(param.first, param.second); + } + // Open file stream for the specified file path return file_buffer::open(filePath, std::ios::out) .then([=](streambuf outFile) -> pplx::task { *fileBuffer = outFile; return client->request(methods::GET); }) // Write the response body into the file buffer .then([=](http_response response) -> pplx::task { auto status = response.status_code(); if (status_codes::OK != status) mitkThrow() << "GET ended up with response " << RESTUtil::convertToUtf8(response.to_string()); return response.body().read_to_end(*fileBuffer); }) // Close the file buffer .then([=](size_t) { return fileBuffer->close(); }) // Return empty JSON object .then([=]() { return web::json::value(); }); } pplx::task mitk::RESTClient::Put(const web::uri &uri, const web::json::value *content) { auto client = new http_client(uri); http_request request(methods::PUT); if (nullptr != content) request.set_body(*content); return client->request(request).then([=](pplx::task responseTask) { try { auto response = responseTask.get(); auto status = response.status_code(); if (status_codes::OK != status) mitkThrow(); // Parse content type to application/json if it isn't already. This is // important if the content type is e.g. application/dicom+json. auto requestContentType = response.headers().content_type(); if (_XPLATSTR("application/json") != requestContentType) response.headers().set_content_type(_XPLATSTR("application/json")); return response.extract_json().get(); } catch (...) { mitkThrow() << "Getting response went wrong"; } }); } pplx::task mitk::RESTClient::Post(const web::uri &uri, const web::json::value *content) { auto client = new http_client(uri); http_request request(methods::POST); if (nullptr != content) request.set_body(*content); return client->request(request).then([=](pplx::task responseTask) { try { auto response = responseTask.get(); auto status = response.status_code(); if (status_codes::Created != status) mitkThrow(); // Parse content type to application/json if it isn't already. This is // important if the content type is e.g. application/dicom+json. auto requestContentType = response.headers().content_type(); if (_XPLATSTR("application/json") != requestContentType) response.headers().set_content_type(_XPLATSTR("application/json")); return response.extract_json().get(); } catch(...) { mitkThrow() << "Getting response went wrong"; } }); } diff --git a/Modules/RESTService/include/mitkRESTManager.h b/Modules/RESTService/include/mitkRESTManager.h index ea50ffdeea..53d07332b6 100644 --- a/Modules/RESTService/include/mitkRESTManager.h +++ b/Modules/RESTService/include/mitkRESTManager.h @@ -1,118 +1,119 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkRESTManager_h #define mitkRESTManager_h -#include #include +#include namespace mitk { /** - * @class RESTManager - * @brief this is a microservice for managing REST-requests, used for non-qt applications. - * - * RESTManagerQt in the CppRestSdkQt module inherits from this class and is the equivalent microservice - * used for Qt applications. - */ + * @class RESTManager + * @brief this is a microservice for managing REST-requests, used for non-qt applications. + * + * RESTManagerQt in the CppRestSdkQt module inherits from this class and is the equivalent microservice + * used for Qt applications. + */ class MITKRESTSERVICE_EXPORT RESTManager : public IRESTManager { public: RESTManager(); ~RESTManager() override; /** * @brief Executes a HTTP request in the mitkRESTClient class * * @throw mitk::Exception if RequestType is not suported * @param uri defines the URI the request is send to * @param type the RequestType of the HTTP request (optional) * @param body the body for the request (optional) * @param filePath the file path to store the request to * @return task to wait for */ pplx::task SendRequest(const web::uri &uri, const RequestType &type = RequestType::Get, const web::json::value *body = nullptr, + const std::map headers = {}, const utility::string_t &filePath = {}) override; /** * @brief starts listening for requests if there isn't another observer listening and the port is free * * @param uri defines the URI for which incoming requests should be send to the observer * @param observer the observer which handles the incoming requests */ void ReceiveRequest(const web::uri &uri, IRESTObserver *observer) override; /** * @brief Handles incoming requests by notifying the observer which should receive it * * @param uri defines the URI of the request * @param body the body of the request * @return the data which is modified by the notified observer */ web::json::value Handle(const web::uri &uri, const web::json::value &body) override; /** * @brief Handles the deletion of an observer for all or a specific uri * * @param observer the observer which shouldn't receive requests anymore * @param uri the uri for which the observer doesn't handle requests anymore (optional) */ void HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri = {}) override; /** - * @brief internal use only - */ - const std::map& GetServerMap() override; - std::map, IRESTObserver *>& GetObservers() override; + * @brief internal use only + */ + const std::map &GetServerMap() override; + std::map, IRESTObserver *> &GetObservers() override; private: /** * @brief adds an observer if a port is free, called by ReceiveRequest method * * @param uri the uri which builds the key for the observer map * @param observer the observer which is added */ void AddObserver(const web::uri &uri, IRESTObserver *observer); /** * @brief handles server management if there is already a server under a port, called by ReceiveRequest method * * @param uri the uri which which is requested to be added * @param observer the observer which proceeds the request */ void RequestForATakenPort(const web::uri &uri, IRESTObserver *observer); /** * @brief deletes an observer, called by HandleDeleteObserver method * * @param it the iterator comparing the observers in HandleDeleteObserver method * @return bool if there is another observer under the port */ bool DeleteObserver(std::map, IRESTObserver *>::iterator &it); void SetServerMap(const int port, RESTServer *server); void DeleteFromServerMap(const int port); void SetObservers(const std::pair key, IRESTObserver *observer); - std::map m_ServerMap; // Map with port server pairs + std::map m_ServerMap; // Map with port server pairs std::map, IRESTObserver *> m_Observers; // Map with all observers }; -} +} // namespace mitk #endif diff --git a/Modules/RESTService/src/mitkRESTManager.cpp b/Modules/RESTService/src/mitkRESTManager.cpp index 711be3dc65..092b5883a5 100644 --- a/Modules/RESTService/src/mitkRESTManager.cpp +++ b/Modules/RESTService/src/mitkRESTManager.cpp @@ -1,217 +1,218 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include mitk::RESTManager::RESTManager() { } mitk::RESTManager::~RESTManager() { } pplx::task mitk::RESTManager::SendRequest(const web::uri &uri, const RequestType &type, const web::json::value *content, + const std::map headers, const utility::string_t &filePath) { pplx::task answer; auto client = new RESTClient; switch (type) { case RequestType::Get: answer = !filePath.empty() - ? client->Get(uri, filePath) - : client->Get(uri); + ? client->Get(uri, filePath, headers) + : client->Get(uri, headers); break; case RequestType::Post: if (nullptr == content) MITK_WARN << "Content for put is empty, this will create an empty resource"; answer = client->Post(uri, content); break; case RequestType::Put: if (nullptr == content) MITK_WARN << "Content for put is empty, this will empty the ressource"; answer = client->Put(uri, content); break; default: mitkThrow() << "Request Type not supported"; } return answer; } void mitk::RESTManager::ReceiveRequest(const web::uri &uri, mitk::IRESTObserver *observer) { // New instance of RESTServer in m_ServerMap, key is port of the request auto port = uri.port(); // Checking if port is free to add a new Server if (0 == m_ServerMap.count(port)) { this->AddObserver(uri, observer); // creating server instance auto server = new RESTServer(uri.authority()); // add reference to server instance to map m_ServerMap[port] = server; // start Server server->OpenListener(); } // If there is already a server under this port else { this->RequestForATakenPort(uri, observer); } } web::json::value mitk::RESTManager::Handle(const web::uri &uri, const web::json::value &body) { // Checking if there is an observer for the port and path auto key = std::make_pair(uri.port(), uri.path()); if (0 != m_Observers.count(key)) { return m_Observers[key]->Notify(uri, body); } // No observer under this port, return null which results in status code 404 (s. RESTServer) else { MITK_WARN << "No Observer can handle the data"; return web::json::value(); } } void mitk::RESTManager::HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri) { for (auto it = m_Observers.begin(); it != m_Observers.end();) { mitk::IRESTObserver *obsMap = it->second; // Check wether observer is at this place in map if (observer == obsMap) { // Check wether it is the right uri to be deleted if (uri.is_empty() || uri.path() == it->first.second) { int port = it->first.first; bool noObserverForPort = this->DeleteObserver(it); if (noObserverForPort) { // there isn't an observer at this port, delete m_ServerMap entry for this port // close listener m_ServerMap[port]->CloseListener(); delete m_ServerMap[port]; // delete server from map m_ServerMap.erase(port); } } else { ++it; } } else { ++it; } } } const std::map &mitk::RESTManager::GetServerMap() { return m_ServerMap; } std::map, mitk::IRESTObserver *> &mitk::RESTManager::GetObservers() { return m_Observers; } void mitk::RESTManager::AddObserver(const web::uri &uri, IRESTObserver *observer) { // new observer has to be added std::pair key(uri.port(), uri.path()); m_Observers[key] = observer; } void mitk::RESTManager::RequestForATakenPort(const web::uri &uri, IRESTObserver *observer) { // Same host, means new observer but not a new server instance if (uri.authority() == m_ServerMap[uri.port()]->GetUri()) { // new observer has to be added std::pair key(uri.port(), uri.path()); // only add a new observer if there isn't already an observer for this uri if (0 == m_Observers.count(key)) { this->AddObserver(uri, observer); } else { MITK_ERROR << "Threre is already a observer handeling this data"; } } // Error, since another server can't be added under this port else { MITK_ERROR << "There is already another server listening under this port"; } } bool mitk::RESTManager::DeleteObserver(std::map, IRESTObserver *>::iterator &it) { int port = it->first.first; it = m_Observers.erase(it); for (auto observer : m_Observers) { if (port == observer.first.first) { // there still exists an observer for this port return false; } } return true; } void mitk::RESTManager::SetServerMap(const int port, RESTServer *server) { m_ServerMap[port] = server; } void mitk::RESTManager::DeleteFromServerMap(const int port) { m_ServerMap.erase(port); } void mitk::RESTManager::SetObservers(const std::pair key, IRESTObserver *observer) { m_Observers[key] = observer; } diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index f3316ce4d6..73ca842a78 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,115 +1,116 @@ # Plug-ins must be ordered according to their dependencies set(MITK_PLUGINS org.blueberry.core.runtime:ON org.blueberry.core.expressions:OFF org.blueberry.core.commands:OFF org.blueberry.core.jobs:OFF org.blueberry.ui.qt:OFF org.blueberry.ui.qt.help:ON org.blueberry.ui.qt.log:ON org.blueberry.ui.qt.objectinspector:OFF #org.blueberry.test:ON #org.blueberry.uitest:ON #Testing/org.blueberry.core.runtime.tests:ON #Testing/org.blueberry.osgi.tests:ON org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.chartExample:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.datastorageviewertest:OFF org.mitk.gui.qt.properties:ON org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.dicominspector:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.diffusionimaging.connectomics:OFF org.mitk.gui.qt.diffusionimaging.denoising:OFF org.mitk.gui.qt.diffusionimaging.fiberfox:OFF org.mitk.gui.qt.diffusionimaging.fiberprocessing:OFF org.mitk.gui.qt.diffusionimaging.ivim:OFF org.mitk.gui.qt.diffusionimaging.odfpeaks:OFF org.mitk.gui.qt.diffusionimaging.partialvolume:OFF org.mitk.gui.qt.diffusionimaging.preprocessing:OFF org.mitk.gui.qt.diffusionimaging.reconstruction:OFF org.mitk.gui.qt.diffusionimaging.registration:OFF org.mitk.gui.qt.diffusionimaging.tractography:OFF org.mitk.gui.qt.diffusionimaging.python:OFF org.mitk.gui.qt.dosevisualization:OFF org.mitk.gui.qt.geometrytools:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF org.mitk.gui.qt.lasercontrol:OFF org.mitk.gui.qt.openigtlink:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.viewnavigator:OFF org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.pointsetinteractionmultispectrum:OFF org.mitk.gui.qt.python:OFF org.mitk.gui.qt.remeshing:OFF org.mitk.gui.qt.segmentation:OFF + org.mitk.gui.qt.segmentation.rework:OFF org.mitk.gui.qt.aicpregistration:OFF org.mitk.gui.qt.renderwindowmanager:OFF org.mitk.gui.qt.semanticrelations:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.tubegraph:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.photoacoustics.pausviewer:OFF org.mitk.gui.qt.photoacoustics.pausmotioncompensation:OFF org.mitk.gui.qt.photoacoustics.imageprocessing:OFF org.mitk.gui.qt.photoacoustics.simulation:OFF org.mitk.gui.qt.photoacoustics.spectralunmixing:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF org.mitk.gui.qt.eventrecorder:OFF org.mitk.gui.qt.xnat:OFF org.mitk.gui.qt.igt.app.echotrack:OFF org.mitk.gui.qt.spectrocamrecorder:OFF org.mitk.gui.qt.classificationsegmentation:OFF org.mitk.gui.qt.overlaymanager:OFF org.mitk.gui.qt.igt.app.hummelprotocolmeasurements:OFF org.mitk.gui.qt.multilabelsegmentation:OFF org.mitk.matchpoint.core.helper:OFF org.mitk.gui.qt.matchpoint.algorithm.browser:OFF org.mitk.gui.qt.matchpoint.algorithm.control:OFF org.mitk.gui.qt.matchpoint.algorithm.batch:OFF org.mitk.gui.qt.matchpoint.mapper:OFF org.mitk.gui.qt.matchpoint.framereg:OFF org.mitk.gui.qt.matchpoint.visualizer:OFF org.mitk.gui.qt.matchpoint.evaluator:OFF org.mitk.gui.qt.matchpoint.manipulator:OFF org.mitk.gui.qt.preprocessing.resampling:OFF org.mitk.gui.qt.radiomics:OFF org.mitk.gui.qt.cest:OFF org.mitk.gui.qt.fit.demo:OFF org.mitk.gui.qt.fit.inspector:OFF org.mitk.gui.qt.fit.genericfitting:OFF org.mitk.gui.qt.pharmacokinetics.mri:OFF org.mitk.gui.qt.pharmacokinetics.pet:OFF org.mitk.gui.qt.pharmacokinetics.simulation:OFF org.mitk.gui.qt.pharmacokinetics.curvedescriptor:OFF org.mitk.gui.qt.pharmacokinetics.concentration.mri:OFF ) diff --git a/Plugins/org.mitk.gui.qt.segmentation.rework/CMakeLists.txt b/Plugins/org.mitk.gui.qt.segmentation.rework/CMakeLists.txt index 5df0ad6462..29d5736b38 100644 --- a/Plugins/org.mitk.gui.qt.segmentation.rework/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.segmentation.rework/CMakeLists.txt @@ -1,8 +1,8 @@ project(org_mitk_gui_qt_segmentation_rework) mitk_create_plugin( EXPORT_DIRECTIVE REWORK_EXPORT EXPORTED_INCLUDE_SUFFIXES src - MODULE_DEPENDS MitkQtWidgetsExt MitkCppRestSdk MitkChart MitkSegmentationUI + MODULE_DEPENDS MitkQtWidgetsExt MitkREST MitkRESTService MitkChart MitkSegmentationUI PACKAGE_DEPENDS PUBLIC CTK|CTKWidgets ) diff --git a/Plugins/org.mitk.gui.qt.segmentation.rework/files.cmake b/Plugins/org.mitk.gui.qt.segmentation.rework/files.cmake index a50d3a5697..3b25cdb248 100644 --- a/Plugins/org.mitk.gui.qt.segmentation.rework/files.cmake +++ b/Plugins/org.mitk.gui.qt.segmentation.rework/files.cmake @@ -1,45 +1,46 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES org_mitk_gui_qt_segmentation_rework_Activator.cpp SegmentationReworkView.cpp - SegmentationReworkREST.cpp + ReworkRequestHandler.cpp ) set(UI_FILES src/internal/SegmentationReworkViewControls.ui ) set(MOC_H_FILES src/internal/org_mitk_gui_qt_segmentation_rework_Activator.h src/internal/SegmentationReworkView.h - src/internal/SegmentationReworkREST.h + src/internal/ReworkRequestHandler.h + src/internal/DICOMweb.h ) # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench set(CACHED_RESOURCE_FILES resources/icon.xpm resources/plugin_icon.png plugin.xml ) # list of Qt .qrc files which contain additional resources # specific to this plugin set(QRC_FILES ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/DICOMweb.h b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/DICOMweb.h new file mode 100644 index 0000000000..8115ed396b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/DICOMweb.h @@ -0,0 +1,220 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef DICOMweb_h +#define DICOMweb_h + +#include "cpprest/asyncrt_utils.h" +#include "cpprest/http_client.h" +#include +#include +#include +#include + +#include +#include + +class DICOMweb +{ +public: + typedef web::http::uri_builder MitkUriBuilder; + typedef web::http::http_request MitkRequest; + typedef web::http::http_response MitkResponse; + typedef web::http::methods MitkRESTMethods; + + /** + * @brief Creates a QIDO request URI with the given parameter map + */ + static utility::string_t CreateQIDOUri(mitk::RESTUtil::ParamMap map) + { + MitkUriBuilder queryBuilder(U("rs/instances")); + + for (auto const &element : map) + { + queryBuilder.append_query(element.first, element.second); + } + + return queryBuilder.to_string(); + } + + /** + * @brief Creates a WADO request URI with the given parameter + */ + static utility::string_t CreateWADOUri(utility::string_t studyUID, + utility::string_t seriesUID, + utility::string_t instanceUID) + { + MitkUriBuilder builder(U("wado")); + builder.append_query(U("requestType"), U("WADO")); + builder.append_query(U("studyUID"), studyUID); + builder.append_query(U("seriesUID"), seriesUID); + builder.append_query(U("objectUID"), instanceUID); + builder.append_query(U("contentType"), U("application/dicom")); + + return builder.to_string(); + } + + /** + * @brief Creates a STOW request URI with the given parameter map + */ + static utility::string_t CreateSTOWUri(utility::string_t studyUID) + { + MitkUriBuilder builder(U("rs/studies")); + builder.append_path(studyUID); + return builder.to_string(); + } + + static pplx::task SendSTOW(utility::string_t filePath, utility::string_t studyUID) + { + auto uri = CreateSTOWUri(studyUID); + auto manager = RESTManager(); + + // TODO: complete STOW + return manager->SendRequest(uri, mitk::IRESTManager::RequestType::Post, {}, {}, filePath) + .then([=](web::json::value result){}); + } + + static pplx::task SendWADO(utility::string_t filePath, + utility::string_t studyUID, + utility::string_t seriesUID, + utility::string_t instanceUID, + mitk::IRESTManager *manager) + { + auto uri = CreateWADOUri(studyUID, seriesUID, instanceUID); + + // don't want return something + return manager->SendRequest(uri, mitk::IRESTManager::RequestType::Get, {}, {}, filePath) + .then([=](web::json::value result){}); + } + + static pplx::task SendWADO(utility::string_t folderPath, + utility::string_t studyUID, + utility::string_t seriesUID) + { + mitk::RESTUtil::ParamMap seriesInstances; + seriesInstances.insert(mitk::RESTUtil::ParamMap::value_type(U("StudyInstanceUID"), studyUID)); + seriesInstances.insert(mitk::RESTUtil::ParamMap::value_type(U("SeriesInstanceUID"), seriesUID)); + + auto *manager = RESTManager(); + + return SendQIDO(seriesInstances).then([=](web::json::value jsonResult) -> pplx::task { + auto jsonListResult = jsonResult; + auto resultArray = jsonListResult.as_array(); + + auto firstFileName = std::string(); + + std::vector> tasks; + + for (unsigned short i = 0; i < resultArray.size(); i++) + { + try + { + auto firstResult = resultArray[i]; + auto sopInstanceUIDKey = firstResult.at(U("00080018")); + auto sopInstanceObject = sopInstanceUIDKey.as_object(); + auto valueKey = sopInstanceObject.at(U("Value")); + auto valueArray = valueKey.as_array(); + auto sopInstanceUID = valueArray[0].as_string(); + + auto fileName = utility::string_t(sopInstanceUID).append(U(".dcm")); + + // save first file name as result to load series + if (i == 0) + { + firstFileName = utility::conversions::to_utf8string(fileName); + } + + auto filePath = utility::string_t(folderPath).append(fileName); + auto task = SendWADO(filePath, studyUID, seriesUID, sopInstanceUID, manager); + tasks.push_back(task); + } + catch (const web::json::json_exception &e) + { + MITK_ERROR << e.what(); + } + } + + auto joinTask = pplx::when_all(begin(tasks), end(tasks)); + + auto returnTask = joinTask.then([=](void) -> std::string { + auto folderPathUtf8 = utility::conversions::to_utf8string(folderPath); + auto result = folderPathUtf8 + firstFileName; + + return result; + }); + + return returnTask; + }); + } + + static pplx::task SendQIDO(mitk::RESTUtil::ParamMap map) + { + auto uri = CreateQIDOUri(map); + + auto *manager = RESTManager(); + + mitk::RESTUtil::ParamMap headers; + headers.insert(mitk::RESTUtil::ParamMap::value_type(U("Accept"), U("application/json"))); + + return manager->SendRequest(uri, mitk::IRESTManager::RequestType::Get, {}, headers); + // return manager->SendRequest(queryBuilder.to_string()).then([=](pplx::task taskResponse) { + // try + // { + // MitkResponse response = taskResponse.get(); + // auto status = response.status_code(); + // MITK_INFO << " status: " << status; + + // if (status != web::http::status_codes::OK) + // { + // MITK_ERROR << "no dicom series found for query " + // << utility::conversions::to_utf8string(queryBuilder.to_string()); + // mitkThrow() << "no dicom series found for query " + // << utility::conversions::to_utf8string(queryBuilder.to_string()); + // } + + // if (response.headers()[U("Content-Type")] == U("application/dicom+json")) + // { + // response.headers().remove(U("Content-Type")); + // response.headers().add(U("Content-Type"), U("application/json")); + // } + + // return response.extract_json().get(); + // } + // catch (std::exception &e) + // { + // mitkThrow() << e.what(); + // } + //}); + } + +private: + static mitk::IRESTManager *RESTManager() + { + auto *context = us::GetModuleContext(); + auto managerRef = context->GetServiceReference(); + if (managerRef) + { + auto managerService = context->GetService(managerRef); + if (managerService) + { + return managerService; + } + } + return nullptr; + } +}; + +#endif // DICOMweb_h diff --git a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/ReworkRequestHandler.cpp b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/ReworkRequestHandler.cpp new file mode 100644 index 0000000000..f9d2286687 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/ReworkRequestHandler.cpp @@ -0,0 +1,176 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include "DICOMweb.h" +#include "ReworkRequestHandler.h" +//#include +#include + +#include +#include + +ReworkRequestHandler::ReworkRequestHandler() {} + +ReworkRequestHandler::ReworkRequestHandler(std::string downloadDir) : m_DownloadDir{downloadDir} +{ + auto *context = us::GetModuleContext(); + auto managerRef = context->GetServiceReference(); + if (managerRef) + { + auto managerService = context->GetService(managerRef); + if (managerService) + { + m_ManagerService = managerService; + } + } +} + +ReworkRequestHandler::~ReworkRequestHandler() {} + +ReworkRequestHandler::DicomDTO ReworkRequestHandler::ExtractDTO(const web::json::value &data) +{ + DicomDTO dto; + auto messageTypeKey = data.at(L"messageType"); + if (messageTypeKey.as_string() == L"downloadData") + { + auto imageStudyUIDKey = data.at(L"studyUID"); + auto srSeriesUIDKey = data.at(L"srSeriesUID"); + + auto groundTruthKey = data.at(L"groundTruth"); + + auto simScoreKey = data.at(L"simScoreArray"); + auto minSliceStartKey = data.at(L"minSliceStart"); + + dto.srSeriesUID = srSeriesUIDKey.as_string(); + dto.groundTruth = groundTruthKey.as_string(); + dto.studyUID = imageStudyUIDKey.as_string(); + dto.minSliceStart = minSliceStartKey.as_integer(); + + std::vector vec; + web::json::array simArray = simScoreKey.as_array(); + + for (web::json::value score : simArray) + { + vec.push_back(score.as_double() * 100); + } + + dto.simScoreArray = vec; + } + return dto; +} + +web::json::value ReworkRequestHandler::Notify(const web::uri &uri, const web::json::value &data) +{ + emit InvokeProgress(20, {"display graph and query structured report"}); + + DicomDTO dto = ExtractDTO(data); + + emit InvokeSimilarityGraph(dto.simScoreArray, dto.minSliceStart); + emit InvokeUpdateDcmMeta(dto); + + mitk::RESTUtil::ParamMap seriesInstancesParams; + + seriesInstancesParams.insert(mitk::RESTUtil::ParamMap::value_type(L"StudyInstanceUID", dto.studyUID)); + seriesInstancesParams.insert(mitk::RESTUtil::ParamMap::value_type(L"SeriesInstanceUID", dto.srSeriesUID)); + seriesInstancesParams.insert( + mitk::RESTUtil::ParamMap::value_type(L"includefield", + L"0040A375")); // Current Requested Procedure Evidence Sequence + + try + { + auto requestURI = DICOMweb::CreateQIDOUri(seriesInstancesParams); + + m_ManagerService->SendRequest(requestURI).then([=](web::json::value jsonResult) { + auto firstResult = jsonResult[0]; + auto actualListKey = firstResult.at(L"0040A375") + .as_object() + .at(L"Value") + .as_array()[0] + .as_object() + .at(L"00081115") + .as_object() + .at(L"Value") + .as_array(); + + utility::string_t segSeriesUIDA = {}; + utility::string_t segSeriesUIDB = {}; + utility::string_t imageSeriesUID = {}; + + for (unsigned int index = 0; index < actualListKey.size(); index++) + { + auto element = actualListKey[index].as_object(); + // get SOP class UID + auto innerElement = element.at(L"00081199").as_object().at(L"Value").as_array()[0]; + auto sopClassUID = innerElement.at(L"00081150").as_object().at(L"Value").as_array()[0].as_string(); + + auto seriesUID = element.at(L"0020000E").as_object().at(L"Value").as_array()[0].as_string(); + + if (sopClassUID == L"1.2.840.10008.5.1.4.1.1.66.4") // SEG + { + if (segSeriesUIDA.length() == 0) + { + segSeriesUIDA = seriesUID; + } + else + { + segSeriesUIDB = seriesUID; + } + } + else if (sopClassUID == L"1.2.840.10008.5.1.4.1.1.2") // CT + { + imageSeriesUID = seriesUID; + } + } + + emit InvokeProgress(10, {"load composite context of structured report"}); + MITK_INFO << "image series UID " << mitk::RESTUtil::convertToUtf8(imageSeriesUID); + MITK_INFO << "seg A series UID " << mitk::RESTUtil::convertToUtf8(segSeriesUIDA); + MITK_INFO << "seg B series UID " << mitk::RESTUtil::convertToUtf8(segSeriesUIDB); + + MITK_INFO << "Load related dicom series ..."; + + std::string folderPathSeries = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadDir) + "/"; + + std::string pathSegA = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadDir) + "/"; + std::string pathSegB = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadDir) + "/"; + + auto folderPathSegA = utility::conversions::to_string_t(pathSegA); + auto folderPathSegB = utility::conversions::to_string_t(pathSegB); + + std::vector> tasks; + + auto imageSeriesTask = + DICOMweb::SendWADO(utility::conversions::to_string_t(folderPathSeries), dto.studyUID, imageSeriesUID); + auto segATask = DICOMweb::SendWADO(folderPathSegA, dto.studyUID, segSeriesUIDA); + auto segBTask = DICOMweb::SendWADO(folderPathSegB, dto.studyUID, segSeriesUIDB); + tasks.push_back(imageSeriesTask); + tasks.push_back(segATask); + tasks.push_back(segBTask); + + auto joinTask = pplx::when_all(begin(tasks), end(tasks)); + auto filePathList = joinTask.then([&](std::vector filePathList) { + emit InvokeProgress(50, {"load dicom files from disk"}); + emit InvokeLoadData(filePathList); + }); + }); + } + catch (mitk::Exception &e) + { + MITK_ERROR << e.what(); + } + return web::json::value(); +} \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/ReworkRequestHandler.h b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/ReworkRequestHandler.h new file mode 100644 index 0000000000..86590381ee --- /dev/null +++ b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/ReworkRequestHandler.h @@ -0,0 +1,62 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef ReworkRequestHandler_h +#define ReworkRequestHandler_h + +#include +#include +#include + +class ReworkRequestHandler : public QObject, public mitk::IRESTObserver +{ + Q_OBJECT +public: + struct DicomDTO + { + utility::string_t segSeriesUIDA; + utility::string_t segSeriesUIDB; + utility::string_t imageSeriesUID; + utility::string_t studyUID; + utility::string_t segInstanceUIDA; + utility::string_t segInstanceUIDB; + utility::string_t srSeriesUID; + std::vector seriesUIDList; + std::vector simScoreArray; + int minSliceStart; + utility::string_t groundTruth; + }; + + ReworkRequestHandler(); + ReworkRequestHandler(std::string downloadDir); + ~ReworkRequestHandler(); + + web::json::value Notify(const web::uri &uri, const web::json::value &data); + +signals: + void InvokeProgress(int, QString status); + void InvokeSimilarityGraph(std::vector score, int sliceStart); + void InvokeUpdateDcmMeta(DicomDTO dto); + void InvokeLoadData(std::vector); + +private: + DicomDTO ExtractDTO(const web::json::value &data); + + mitk::IRESTManager *m_ManagerService; + std::string m_DownloadDir; +}; + +#endif // ReworkRequestHandler_h diff --git a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.cpp b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.cpp deleted file mode 100644 index b5c8141676..0000000000 --- a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#include -#include - -#include "SegmentationReworkREST.h" -#include -#include - -SegmentationReworkREST::SegmentationReworkREST() {} - -SegmentationReworkREST::SegmentationReworkREST(utility::string_t url) : mitk::RESTServer(url) -{ - m_Listener.support(MitkRESTMethods::PUT, std::bind(&SegmentationReworkREST::HandlePut, this, std::placeholders::_1)); - m_Listener.support(MitkRESTMethods::GET, std::bind(&SegmentationReworkREST::HandleGet, this, std::placeholders::_1)); - m_Listener.support(MitkRESTMethods::OPTIONS, std::bind(&SegmentationReworkREST::HandleOptions, this, std::placeholders::_1)); -} - -SegmentationReworkREST::~SegmentationReworkREST() {} - -void SegmentationReworkREST::HandleOptions(MitkRequest message) -{ - auto messageString = message.to_string(); - MITK_INFO << "Message OPTIONS incoming..."; - MITK_INFO << mitk::RESTUtil::convertToUtf8(messageString); - - MitkResponse response(MitkRestStatusCodes::OK); - response.headers().add(U("Access-Control-Allow-Methods"), "PUT"); - response.headers().add(U("Access-Control-Allow-Headers"), "Content-Type"); - response.headers().add(U("Access-Control-Allow-Origin"), mitk::RESTUtil::convertToTString(m_AllowOrigin)); - - message.reply(response); -} - -void SegmentationReworkREST::HandleGet(MitkRequest message) -{ - auto messageString = message.to_string(); - MITK_INFO << "Message GET incoming..."; - MITK_INFO << mitk::RESTUtil::convertToUtf8(messageString); - - MITK_INFO << mitk::RESTUtil::convertToUtf8(message.request_uri().to_string()); - auto uri = web::uri::decode(message.request_uri().to_string()); - - if (uri.find(U("/robots.txt")) != std::string::npos || uri.find(U("/favicon.ico")) != std::string::npos || - uri == U("/-") || uri.length() == 0) - { - MITK_INFO << "ignore GET request: " << mitk::RESTUtil::convertToUtf8(messageString); - return; - } - - auto query = web::uri(uri).query(); - auto httpParams = web::uri::split_query(query); - - // IHE Invoke Image Display style - auto requestType = httpParams.find(U("requestType")); - MITK_INFO << "parameters found: " << httpParams.size(); - - MitkResponse responsePositive(MitkRestStatusCodes::OK); - responsePositive.set_body("call to mitk was successfully!"); - - if (requestType != httpParams.end() && requestType->second == U("IMAGE_SEG")) - { - try - { - auto studyUID = httpParams.at(U("studyUID")); - auto imageSeriesUID = httpParams.at(U("imageSeriesUID")); - auto segSeriesUID = httpParams.at(U("segSeriesUID")); - - DicomDTO dto; - dto.imageSeriesUID = mitk::RESTUtil::convertToUtf8(imageSeriesUID); - dto.studyUID = mitk::RESTUtil::convertToUtf8(studyUID); - dto.segSeriesUIDA = mitk::RESTUtil::convertToUtf8(segSeriesUID); - - MITK_INFO << "studyUID: " << dto.studyUID; - MITK_INFO << "imageSeriesUID: " << dto.imageSeriesUID; - MITK_INFO << "segSeriesUID: " << dto.segSeriesUIDA; - - m_GetImageSegCallback(dto); - - MitkResponse response(MitkRestStatusCodes::OK); - message.reply(responsePositive); - } - catch (std::out_of_range &e) - { - message.reply(MitkRestStatusCodes::BadRequest, "oh man, that was not expected: " + std::string(e.what())); - } - } - else if (requestType != httpParams.end() && requestType->second == U("SEG_EVALUATION")) - { - // TODO: implement PUT handling as GET - } - else if (requestType != httpParams.end() && requestType->second == U("IMAGE_SEG_LIST")) - { - auto studyUID = httpParams.at(U("studyUID")); - auto imageSeriesUID = httpParams.at(U("imageSeriesUID")); - auto segSeriesUIDList = httpParams.at(U("segSeriesUIDList")); - - DicomDTO dto; - dto.imageSeriesUID = mitk::RESTUtil::convertToUtf8(imageSeriesUID); - dto.studyUID = mitk::RESTUtil::convertToUtf8(studyUID); - - auto segSeriesUIDListUtf8 = mitk::RESTUtil::convertToUtf8(segSeriesUIDList); - - std::istringstream f(segSeriesUIDListUtf8); - std::string s; - while (getline(f, s, ',')) - { - dto.seriesUIDList.push_back(s); - } - - MITK_INFO << "studyUID: " << dto.studyUID; - MITK_INFO << "imageSeriesUID: " << dto.imageSeriesUID; - MITK_INFO << "segSeriesUIDList: " << segSeriesUIDListUtf8; - - m_GetImageSegCallback(dto); - - message.reply(responsePositive); - } - else if (requestType != httpParams.end() && requestType->second == U("ADD_SERIES")) - { - auto studyUID = httpParams.at(U("studyUID")); - auto segSeriesUIDList = httpParams.at(U("seriesUIDList")); - - DicomDTO dto; - dto.studyUID = mitk::RESTUtil::convertToUtf8(studyUID); - - auto seriesUIDListUtf8 = mitk::RESTUtil::convertToUtf8(segSeriesUIDList); - - std::istringstream f(seriesUIDListUtf8); - std::string s; - while (getline(f, s, ',')) - { - dto.seriesUIDList.push_back(s); - } - - MITK_INFO << "studyUID: " << dto.studyUID; - MITK_INFO << "seriesUIDList: " << seriesUIDListUtf8; - - m_GetAddSeriesCallback(dto); - message.reply(responsePositive); - } - else - { - message.reply(MitkRestStatusCodes::BadRequest, - "unknown request type " + mitk::RESTUtil::convertToUtf8(requestType->second)); - } -} - -void SegmentationReworkREST::HandlePut(MitkRequest message) -{ - auto messageString = message.to_string(); - MITK_INFO << "Message PUT incoming..."; - MITK_INFO << mitk::RESTUtil::convertToUtf8(messageString); - - try - { - auto jsonMessage = message.extract_json().get(); - - auto messageTypeKey = jsonMessage.at(U("messageType")); - if (messageTypeKey.as_string() == U("downloadData")) - { - auto imageStudyUIDKey = jsonMessage.at(U("studyUID")); - auto srSeriesUIDKey = jsonMessage.at(U("srSeriesUID")); - - auto groundTruthKey = jsonMessage.at(U("groundTruth")); - - auto simScoreKey = jsonMessage.at(U("simScoreArray")); - auto minSliceStartKey = jsonMessage.at(U("minSliceStart")); - - DicomDTO dto; - dto.srSeriesUID = mitk::RESTUtil::convertToUtf8(srSeriesUIDKey.as_string()); - - dto.groundTruth = mitk::RESTUtil::convertToUtf8(groundTruthKey.as_string()); - - dto.studyUID = mitk::RESTUtil::convertToUtf8(imageStudyUIDKey.as_string()); - dto.minSliceStart = minSliceStartKey.as_integer(); - - std::vector vec; - web::json::array simArray = simScoreKey.as_array(); - - for (web::json::value score : simArray) - { - vec.push_back(score.as_double() * 100); - } - - dto.simScoreArray = vec; - m_PutCallback(dto); - emit InvokeUpdateChartWidget(); - } - else - { - message.reply(MitkRestStatusCodes::BadRequest, "Oh man, i can only deal with 'messageType' = 'downloadData'..."); - } - } - catch (MitkJsonException &e) - { - MITK_ERROR << e.what() << ".. oh man, that was not expected"; - message.reply(MitkRestStatusCodes::BadRequest, "oh man, that was not expected"); - return; - } - MitkResponse response(MitkRestStatusCodes::OK); - response.headers().add(U("Access-Control-Allow-Origin"), mitk::RESTUtil::convertToTString(m_AllowOrigin)); - response.set_body("Sure, i got you.. have an awesome day"); - message.reply(response); - return; -} \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.h b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.h deleted file mode 100644 index 85b819ef6f..0000000000 --- a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.h +++ /dev/null @@ -1,75 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#ifndef SegmentationReworkREST_h -#define SegmentationReworkREST_h - -#include - -class SegmentationReworkREST : public mitk::RESTServer -{ - Q_OBJECT - -public: - struct DicomDTO - { - std::string segSeriesUIDA; - std::string segSeriesUIDB; - std::string imageSeriesUID; - std::string studyUID; - std::string segInstanceUIDA; - std::string segInstanceUIDB; - std::string srSeriesUID; - std::vector seriesUIDList; - std::vector simScoreArray; - int minSliceStart; - std::string groundTruth; - }; - - SegmentationReworkREST(); - SegmentationReworkREST(utility::string_t url); - ~SegmentationReworkREST(); - - void HandlePut(MitkRequest message); - void HandleGet(MitkRequest message); - void HandleOptions(MitkRequest message); - - void SetPutCallback(std::function callback) { m_PutCallback = callback; } - - void SetGetImageSegCallback(std::function callback) { m_GetImageSegCallback = callback; } - - void SetGetEvalCallback(std::function callback) { m_GetEvalCallback = callback; } - - void SetGetAddSeriesCallback(std::function callback) { m_GetAddSeriesCallback = callback; } - - void SetAllowOrigin(std::string origin) - { - m_AllowOrigin = origin; - } - -signals: - void InvokeUpdateChartWidget(); - -private: - std::function m_PutCallback; - std::function m_GetImageSegCallback; - std::function m_GetEvalCallback; - std::function m_GetAddSeriesCallback; - - std::string m_AllowOrigin; -}; - -#endif // SegmentationReworkREST_h diff --git a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.cpp b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.cpp index 25f102bee0..1282a5b7ba 100644 --- a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.cpp @@ -1,704 +1,561 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "SegmentationReworkView.h" #include // Qt #include #include #include #include #include #include #include #include #include #include #include +#include +#include +#include + +#include "DICOMweb.h" +#include "ReworkRequestHandler.h" + #include #include const std::string SegmentationReworkView::VIEW_ID = "org.mitk.views.segmentationreworkview"; void SegmentationReworkView::SetFocus() {} void SegmentationReworkView::CreateQtPartControl(QWidget *parent) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); m_Parent = parent; counter = 0; qRegisterMetaType>("std::vector"); // m_Controls.verticalWidget->setVisible(false); m_Controls.cleanDicomBtn->setVisible(false); m_Controls.individualWidget_2->setVisible(false); m_Controls.sliderWidget->setMinimum(1); m_Controls.sliderWidget->setMaximum(100); m_Controls.sliderWidget->setTickInterval(1); m_Controls.sliderWidget->setSingleStep(1); m_Controls.radioA->setChecked(true); connect(m_Controls.buttonUpload, &QPushButton::clicked, this, &SegmentationReworkView::UploadNewSegmentation); connect(m_Controls.buttonNewSeg, &QPushButton::clicked, this, &SegmentationReworkView::CreateNewSegmentationC); connect(m_Controls.cleanDicomBtn, &QPushButton::clicked, this, &SegmentationReworkView::CleanDicomFolder); connect(m_Controls.restartConnection, &QPushButton::clicked, this, &SegmentationReworkView::OnRestartConnection); connect(m_Controls.testConnection, &QPushButton::clicked, this, &SegmentationReworkView::TestConnection); connect(m_Controls.checkIndiv, &QCheckBox::stateChanged, this, &SegmentationReworkView::OnIndividualCheckChange); connect( m_Controls.sliderWidget, &ctkSliderWidget::valueChanged, this, &SegmentationReworkView::OnSliderWidgetChanged); m_DownloadBaseDir = mitk::IOUtil::GetTempPath() + "segrework"; MITK_INFO << "using download base dir: " << m_DownloadBaseDir; m_UploadBaseDir = mitk::IOUtil::GetTempPath() + "uploadSeg"; if (!itksys::SystemTools::FileIsDirectory(m_DownloadBaseDir)) { itk::FileTools::CreateDirectory(m_DownloadBaseDir); } if (!itksys::SystemTools::FileIsDirectory(m_UploadBaseDir)) { itk::FileTools::CreateDirectory(m_UploadBaseDir); } utility::string_t port = U("2020"); utility::string_t address = U("http://127.0.0.1:"); address.append(port); - m_HttpHandler = std::unique_ptr(new SegmentationReworkREST(address)); + // m_HttpHandler = std::unique_ptr(new SegmentationReworkREST(address)); - connect(m_HttpHandler.get(), - &SegmentationReworkREST::InvokeUpdateChartWidget, - this, - &SegmentationReworkView::UpdateChartWidget); - connect(this, &SegmentationReworkView::InvokeLoadData, this, &SegmentationReworkView::LoadData); + // connect(m_HttpHandler.get(), + // &SegmentationReworkREST::InvokeUpdateChartWidget, + // this, + // &SegmentationReworkView::UpdateChartWidget); + connect(this, &SegmentationReworkView::InvokeLoadData, this, &SegmentationReworkView::LoadData); connect(this, &SegmentationReworkView::InvokeProgress, this, &SegmentationReworkView::AddProgress); + connect(m_RequestHandler, &ReworkRequestHandler::InvokeProgress, this, &SegmentationReworkView::AddProgress); + connect(m_RequestHandler, &ReworkRequestHandler::InvokeSimilarityGraph, this, &SegmentationReworkView::SetSimilarityGraph); + connect(m_RequestHandler, &ReworkRequestHandler::InvokeUpdateDcmMeta, this, &SegmentationReworkView::UpdateDcmMeta); + connect(m_RequestHandler, &ReworkRequestHandler::InvokeLoadData, this, &SegmentationReworkView::LoadData); + + // m_HttpHandler->SetPutCallback(std::bind(&SegmentationReworkView::RESTPutCallback, this, std::placeholders::_1)); + // m_HttpHandler->SetGetImageSegCallback( + // std::bind(&SegmentationReworkView::RESTGetCallback, this, std::placeholders::_1)); + // m_HttpHandler->SetGetAddSeriesCallback( + // std::bind(&SegmentationReworkView::RESTGetCallbackGeneric, this, std::placeholders::_1)); + // m_HttpHandler->Open().wait(); + + auto *context = us::GetModuleContext(); + auto managerRef = context->GetServiceReference(); + if (managerRef) + { + auto managerService = context->GetService(managerRef); + if (managerService) + { + m_ManagerService = managerService; + } + } - m_HttpHandler->SetPutCallback(std::bind(&SegmentationReworkView::RESTPutCallback, this, std::placeholders::_1)); - m_HttpHandler->SetGetImageSegCallback( - std::bind(&SegmentationReworkView::RESTGetCallback, this, std::placeholders::_1)); - m_HttpHandler->SetGetAddSeriesCallback( - std::bind(&SegmentationReworkView::RESTGetCallbackGeneric, this, std::placeholders::_1)); - m_HttpHandler->Open().wait(); - + m_RequestHandler = new ReworkRequestHandler(m_DownloadBaseDir); + m_ManagerService->ReceiveRequest(U("http://127.0.0.1:2020"), m_RequestHandler); MITK_INFO << "Listening for requests at: " << utility::conversions::to_utf8string(address); // utility::string_t pacsURL = U("http://jip-dktk/dcm4chee-arc/aets/DCM4CHEE"); utility::string_t restURL = U("http://localhost:8000"); - //m_HttpHandler->SetAllowOrigin("https://10.128.129.136"); + // m_HttpHandler->SetAllowOrigin("https://10.128.129.136"); // RestartConnection("http://e230-pc03.inet.dkfz-heidelberg.de:8090"); - m_HttpHandler->SetAllowOrigin("https://10.128.129.136"); + // m_HttpHandler->SetAllowOrigin("https://10.128.129.136"); - RestartConnection("http://10.128.129.136:8080"); - m_RestService = new mitk::RESTClient(restURL); + // RestartConnection("http://10.128.129.136:8080"); + // m_RestService = new mitk::RESTClient(restURL); } void SegmentationReworkView::OnSliderWidgetChanged(double value) { std::map::iterator it; unsigned int count = 0; for (it = m_ScoreMap.begin(); it != m_ScoreMap.end(); it++) { if (it->second < value) { count++; } } QString labelsToDelete = "slices to delete: " + QString::number(count); m_Controls.slicesToDeleteLabel->setText(labelsToDelete); std::map thresholdMap; for (it = m_ScoreMap.begin(); it != m_ScoreMap.end(); it++) { thresholdMap.insert(std::map::value_type(it->first, value)); } m_Controls.chartWidget->RemoveData(m_thresholdLabel); m_Controls.chartWidget->AddData2D(thresholdMap, m_thresholdLabel); m_Controls.chartWidget->SetChartType(m_thresholdLabel, QmitkChartWidget::ChartType::line); m_Controls.chartWidget->Show(); } void SegmentationReworkView::AddProgress(int progress, QString status) { auto futureValue = m_Controls.progressBar->value() + progress; if (futureValue >= 100) { m_Controls.progressBar->setValue(0); m_Controls.progressBar->setFormat(""); } else { m_Controls.progressBar->setFormat(status.append(" %p%")); m_Controls.progressBar->setValue(futureValue); } } +void SegmentationReworkView::UpdateDcmMeta(ReworkRequestHandler::DicomDTO dto) +{ + m_CurrentStudyUID = mitk::RESTUtil::convertToUtf8(dto.studyUID); + m_SRUID = mitk::RESTUtil::convertToUtf8(dto.srSeriesUID); + m_GroundTruth = mitk::RESTUtil::convertToUtf8(dto.groundTruth); +} + pplx::task SegmentationReworkView::TestConnection() { - typedef std::map ParamMap; - ParamMap seriesInstancesParams; + mitk::RESTUtil::ParamMap seriesInstancesParams; - seriesInstancesParams.insert((ParamMap::value_type({"limit"}, {"1"}))); + seriesInstancesParams.insert(mitk::RESTUtil::ParamMap::value_type(U("limit"), U("1"))); m_Controls.connectionStatus->setText(QString("Testing connection ...")); - return m_DICOMWeb->QidoRSInstances(seriesInstancesParams).then([=](pplx::task resultTask) { + + auto requestURI = DICOMweb::CreateQIDOUri(seriesInstancesParams); + + return m_ManagerService->SendRequest(requestURI).then([=](pplx::task resultTask) { try { auto result = resultTask.get(); if (!result.is_null()) { m_Controls.connectionStatus->setText(QString("Connection works!")); return true; } else { m_Controls.connectionStatus->setText(QString("Trouble with connection. Not valid!")); return false; } } catch (mitk::Exception &e) { MITK_WARN << e.what(); m_Controls.connectionStatus->setText(QString("No connection possible.")); return false; } }); } void SegmentationReworkView::OnRestartConnection() { RestartConnection(); } void SegmentationReworkView::RestartConnection(std::string newHost) { auto hostBefore = m_Controls.dcm4cheeURL->text(); std::string host; if (newHost.empty()) { host = m_Controls.dcm4cheeHostValue->text().toStdString(); } else { host = newHost; } std::string url = host + "/dcm4chee-arc/aets/DCM4CHEE"; if (!host.empty()) { MITK_INFO << "Restarting connection to " << url << " ..."; m_Controls.connectionStatus->setText(QString("Restarting connection...")); m_Controls.dcm4cheeURL->setText({(utility::conversions::to_utf8string(url).c_str())}); - try - { - m_DICOMWeb = new mitk::DICOMWeb(utility::conversions::to_string_t(url)); - } - catch (std::exception &e) - { - MITK_WARN << e.what(); - m_Controls.dcm4cheeURL->setText(hostBefore); - m_Controls.connectionStatus->setText(QString("Invalid host!")); - return; - } + //try + //{ + // m_ManagerService-> + // m_DICOMWeb = new mitk::DICOMWeb(utility::conversions::to_string_t(url)); + //} + //catch (std::exception &e) + //{ + // MITK_WARN << e.what(); + // m_Controls.dcm4cheeURL->setText(hostBefore); + // m_Controls.connectionStatus->setText(QString("Invalid host!")); + // return; + //} if (!TestConnection().get()) { MITK_INFO << "Restart did not work.."; m_Controls.connectionStatus->setText(QString("No PACS server available under given host!")); } else { MITK_INFO << "requests to pacs are sent to: " << url; } } else { m_Controls.connectionStatus->setText(QString("Host must not be empty!")); } } void SegmentationReworkView::OnIndividualCheckChange(int state) { if (state == Qt::Unchecked) { m_Controls.individualWidget_2->setVisible(false); } else if (state == Qt::Checked) { m_Controls.individualWidget_2->setVisible(true); } } -void SegmentationReworkView::RESTPutCallback(const SegmentationReworkREST::DicomDTO &dto) -{ - emit InvokeProgress(20, {"display graph and query structured report"}); - SetSimilarityGraph(dto.simScoreArray, dto.minSliceStart); - - m_SRUID = dto.srSeriesUID; - m_GroundTruth = dto.groundTruth; - - typedef std::map ParamMap; - ParamMap seriesInstancesParams; - - seriesInstancesParams.insert((ParamMap::value_type({"StudyInstanceUID"}, dto.studyUID))); - seriesInstancesParams.insert((ParamMap::value_type({"SeriesInstanceUID"}, dto.srSeriesUID))); - seriesInstancesParams.insert( - (ParamMap::value_type({"includefield"}, {"0040A375"}))); // Current Requested Procedure Evidence Sequence - - try - { - m_DICOMWeb->QidoRSInstances(seriesInstancesParams).then([=](web::json::value jsonResult) { - auto firstResult = jsonResult[0]; - auto actualListKey = firstResult.at(U("0040A375")) - .as_object() - .at(U("Value")) - .as_array()[0] - .as_object() - .at(U("00081115")) - .as_object() - .at(U("Value")) - .as_array(); - - std::string segSeriesUIDA = ""; - std::string segSeriesUIDB = ""; - std::string imageSeriesUID = ""; - - for (unsigned int index = 0; index < actualListKey.size(); index++) - { - auto element = actualListKey[index].as_object(); - // get SOP class UID - auto innerElement = element.at(U("00081199")).as_object().at(U("Value")).as_array()[0]; - auto sopClassUID = innerElement.at(U("00081150")).as_object().at(U("Value")).as_array()[0].as_string(); - - auto seriesUID = utility::conversions::to_utf8string( - element.at(U("0020000E")).as_object().at(U("Value")).as_array()[0].as_string()); - - if (sopClassUID == U("1.2.840.10008.5.1.4.1.1.66.4")) // SEG - { - if (segSeriesUIDA.length() == 0) - { - segSeriesUIDA = seriesUID; - } - else - { - segSeriesUIDB = seriesUID; - } - } - else if (sopClassUID == U("1.2.840.10008.5.1.4.1.1.2")) // CT - { - imageSeriesUID = seriesUID; - } - } - - emit InvokeProgress(10, {"load composite context of structured report"}); - MITK_INFO << "image series UID " << imageSeriesUID; - MITK_INFO << "seg A series UID " << segSeriesUIDA; - MITK_INFO << "seg B series UID " << segSeriesUIDB; - - MITK_INFO << "Load related dicom series ..."; - - std::string folderPathSeries = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadBaseDir) + "/"; - - std::string pathSegA = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadBaseDir) + "/"; - std::string pathSegB = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadBaseDir) + "/"; - - auto folderPathSegA = utility::conversions::to_string_t(pathSegA); - auto folderPathSegB = utility::conversions::to_string_t(pathSegB); - - m_CurrentStudyUID = dto.studyUID; - - std::vector> tasks; - auto imageSeriesTask = - m_DICOMWeb->WadoRS(utility::conversions::to_string_t(folderPathSeries), dto.studyUID, imageSeriesUID); - auto segATask = m_DICOMWeb->WadoRS(folderPathSegA, dto.studyUID, segSeriesUIDA); - auto segBTask = m_DICOMWeb->WadoRS(folderPathSegB, dto.studyUID, segSeriesUIDB); - tasks.push_back(imageSeriesTask); - tasks.push_back(segATask); - tasks.push_back(segBTask); - - auto joinTask = pplx::when_all(begin(tasks), end(tasks)); - auto filePathList = joinTask.then([&](std::vector filePathList) { - emit InvokeProgress(50, {"load dicom files from disk"}); - InvokeLoadData(filePathList); - }); - }); - } - catch (mitk::Exception &e) - { - MITK_ERROR << e.what(); - } -} - -void SegmentationReworkView::RESTGetCallbackGeneric(const SegmentationReworkREST::DicomDTO &dto) -{ - std::vector> tasks; - - if (dto.seriesUIDList.size() > 0) - { - for (std::string segSeriesUID : dto.seriesUIDList) - { - std::string folderPathSeries = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadBaseDir) + "/"; - try - { - auto seriesTask = - m_DICOMWeb->WadoRS(utility::conversions::to_string_t(folderPathSeries), dto.studyUID, segSeriesUID); - tasks.push_back(seriesTask); - } - catch (const mitk::Exception &exception) - { - MITK_INFO << exception.what(); - return; - } - } - } - - try - { - auto joinTask = pplx::when_all(begin(tasks), end(tasks)); - auto filePathList = joinTask.then([&](std::vector filePathList) { InvokeLoadData(filePathList); }); - } - catch (const mitk::Exception &exception) - { - MITK_INFO << exception.what(); - return; - } -} - -void SegmentationReworkView::RESTGetCallback(const SegmentationReworkREST::DicomDTO &dto) -{ - std::string folderPathSeries = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadBaseDir) + "/"; - - MITK_INFO << folderPathSeries; - - std::string pathSeg = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadBaseDir) + "/"; - auto folderPathSeg = utility::conversions::to_string_t(pathSeg); - - MITK_INFO << pathSeg; - - try - { - std::vector> tasks; - auto imageSeriesTask = - m_DICOMWeb->WadoRS(utility::conversions::to_string_t(folderPathSeries), dto.studyUID, dto.imageSeriesUID); - - tasks.push_back(imageSeriesTask); - - if (dto.seriesUIDList.size() > 0) - { - for (std::string segSeriesUID : dto.seriesUIDList) - { - auto segTask = m_DICOMWeb->WadoRS(folderPathSeg, dto.studyUID, segSeriesUID); - tasks.push_back(segTask); - } - } - else - { - auto segATask = m_DICOMWeb->WadoRS(folderPathSeg, dto.studyUID, dto.segSeriesUIDA); - tasks.push_back(segATask); - } - - auto joinTask = pplx::when_all(begin(tasks), end(tasks)); - auto filePathList = joinTask.then([&](std::vector filePathList) { InvokeLoadData(filePathList); }); - } - catch (const mitk::Exception &exception) - { - MITK_INFO << exception.what(); - } -} - std::string SegmentationReworkView::GetAlgorithmOfSegByPath(std::string path) { auto scanner = mitk::DICOMDCMTKTagScanner::New(); mitk::DICOMTagPath algorithmName; algorithmName.AddAnySelection(0x0062, 0x0002).AddElement(0x0062, 0x0009); mitk::StringList files; files.push_back(path); scanner->SetInputFiles(files); scanner->AddTagPath(algorithmName); scanner->Scan(); mitk::DICOMDatasetAccessingImageFrameList frames = scanner->GetFrameInfoList(); auto findings = frames.front()->GetTagValueAsString(algorithmName); if (findings.size() != 0) MITK_INFO << findings.front().value; return findings.front().value; } void SegmentationReworkView::LoadData(std::vector filePathList) { MITK_INFO << "Loading finished. Pushing data to data storage ..."; auto ds = GetDataStorage(); auto dataNodes = mitk::IOUtil::Load(filePathList, *ds); // reinit view mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(ds); // find data nodes m_Image = dataNodes->at(0); m_Image->SetName("image data"); m_SegA = dataNodes->at(1); m_SegB = dataNodes->at(2); auto algorithmNameA = GetAlgorithmOfSegByPath(filePathList[1]); auto algorithmNameB = GetAlgorithmOfSegByPath(filePathList[2]); m_SegA->SetName(algorithmNameA); m_SegB->SetName(algorithmNameB); m_Controls.labelSegAValue->setText(algorithmNameA.c_str()); m_Controls.labelSegBValue->setText(algorithmNameB.c_str()); m_Controls.labelGroundTruthValue->setText(m_GroundTruth.c_str()); emit InvokeProgress(20, {""}); } void SegmentationReworkView::UpdateChartWidget() { m_Controls.chartWidget->Show(); } void SegmentationReworkView::SetSimilarityGraph(std::vector simScoreArray, int sliceMinStart) { std::string label = "similarity graph"; m_thresholdLabel = "threshold"; // m_Controls.chartWidget->Clear(); double sliceIndex = sliceMinStart; for (double score : simScoreArray) { m_ScoreMap.insert(std::map::value_type(sliceIndex, score)); sliceIndex++; } std::map thresholdMap; m_Controls.chartWidget->AddData2D(m_ScoreMap, label); m_Controls.chartWidget->AddData2D(thresholdMap, m_thresholdLabel); m_Controls.chartWidget->SetChartType(label, QmitkChartWidget::ChartType::line); m_Controls.chartWidget->SetChartType(m_thresholdLabel, QmitkChartWidget::ChartType::line); m_Controls.chartWidget->SetXAxisLabel("slice number"); m_Controls.chartWidget->SetYAxisLabel("similarity in percent"); m_Controls.chartWidget->SetTitle("Similartiy Score for Segmentation Comparison"); } void SegmentationReworkView::UploadNewSegmentation() { AddProgress(10, {"save SEG to temp folder"}); std::string folderPathSeg = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_UploadBaseDir) + "/"; const std::string savePath = folderPathSeg + m_SegC->GetName() + ".dcm"; const std::string mimeType = mitk::MitkDICOMQIIOMimeTypes::DICOMSEG_MIMETYPE_NAME(); mitk::IOUtil::Save(m_SegC->GetData(), mimeType, savePath); // get Series Instance UID from new SEG auto scanner = mitk::DICOMDCMTKTagScanner::New(); mitk::DICOMTagPath seriesUID(0x0020, 0x000E); mitk::StringList files; files.push_back(savePath); scanner->SetInputFiles(files); scanner->AddTagPath(seriesUID); scanner->Scan(); mitk::DICOMDatasetAccessingImageFrameList frames = scanner->GetFrameInfoList(); auto findings = frames.front()->GetTagValueAsString(seriesUID); auto segSeriesUID = findings.front().value; AddProgress(20, {"push SEG to PACS"}); auto filePath = utility::conversions::to_string_t(savePath); try { - m_DICOMWeb->StowRS(filePath, m_CurrentStudyUID).then([=] { + DICOMweb::SendSTOW(filePath, mitk::RESTUtil::convertToTString(m_CurrentStudyUID)).then([=] { emit InvokeProgress(80, {"persist reworked SEG to evaluation database"}); - MitkUriBuilder queryBuilder(U("tasks/evaluations/")); - queryBuilder.append_query(U("srUID"), utility::conversions::to_string_t(m_SRUID)); + //MitkUriBuilder queryBuilder(U("tasks/evaluations/")); + //queryBuilder.append_query(U("srUID"), utility::conversions::to_string_t(m_SRUID)); - //m_RestService->Get(queryBuilder.to_string()).then([=](web::json::value result) { + // m_RestService->Get(queryBuilder.to_string()).then([=](web::json::value result) { // MITK_INFO << "after GET"; // MITK_INFO << utility::conversions::to_utf8string(result.to_string()); // auto updatedContent = result.as_array()[0]; // updatedContent[U("reworkedSegmentationUID")] = // web::json::value::string(utility::conversions::to_string_t(segSeriesUID)); // auto id = updatedContent.at(U("id")).as_integer(); // MITK_INFO << id; // auto idParam = std::to_string(id).append("/"); // MitkUriBuilder queryBuilder(U("tasks/evaluations")); // queryBuilder.append_path(utility::conversions::to_string_t(idParam)); // m_RestService->PUT(queryBuilder.to_string(), updatedContent).then([=](web::json::value result) { // MITK_INFO << "successfully stored"; // emit InvokeProgress(30, {"successfully stored"}); // }); //}); }); } catch (const std::exception &exception) { std::cout << exception.what() << std::endl; } } std::vector SegmentationReworkView::CreateSegmentation(mitk::Image::Pointer baseSegmentation, double threshold) { MITK_INFO << "handle individual segmentation creation"; std::map::iterator it; std::vector sliceIndices; unsigned int count = 0; for (it = m_ScoreMap.begin(); it != m_ScoreMap.end(); it++) { if (it->second < threshold) { auto index = it->first; try { mitk::ImagePixelWriteAccessor imageAccessor(baseSegmentation); for (unsigned int x = 0; x < baseSegmentation->GetDimension(0); x++) { for (unsigned int y = 0; y < baseSegmentation->GetDimension(1); y++) { imageAccessor.SetPixelByIndex({{x, y, int(index)}}, 0); } } } catch (mitk::Exception &e) { MITK_ERROR << e.what(); } count++; sliceIndices.push_back(index); MITK_INFO << "slice " << it->first << " removed "; } } MITK_INFO << "slices deleted " << count; return sliceIndices; } void SegmentationReworkView::CreateNewSegmentationC() { mitk::ToolManager *toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); toolManager->InitializeTools(); toolManager->SetReferenceData(m_Image); mitk::Image::Pointer baseImage; if (m_Controls.radioA->isChecked()) { baseImage = dynamic_cast(m_SegA->GetData())->Clone(); } else if (m_Controls.radioB->isChecked()) { baseImage = dynamic_cast(m_SegB->GetData())->Clone(); } if (m_Controls.checkIndiv->isChecked()) { auto sliceIndices = CreateSegmentation(baseImage, m_Controls.sliderWidget->value()); } QmitkNewSegmentationDialog *dialog = new QmitkNewSegmentationDialog(m_Parent); // needs a QWidget as parent, "this" is not QWidget int dialogReturnValue = dialog->exec(); if (dialogReturnValue == QDialog::Rejected) { // user clicked cancel or pressed Esc or something similar return; } // ask the user about an organ type and name, add this information to the image's (!) propertylist // create a new image of the same dimensions and smallest possible pixel type mitk::Tool *firstTool = toolManager->GetToolById(0); if (firstTool) { try { std::string newNodeName = dialog->GetSegmentationName().toStdString(); if (newNodeName.empty()) { newNodeName = "no_name"; } mitk::DataNode::Pointer newSegmentation = firstTool->CreateSegmentationNode(baseImage, newNodeName, dialog->GetColor()); // initialize showVolume to false to prevent recalculating the volume while working on the segmentation newSegmentation->SetProperty("showVolume", mitk::BoolProperty::New(false)); if (!newSegmentation) { return; // could be aborted by user } if (mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetWorkingData(0)) { mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetWorkingData(0)->SetSelected(false); } newSegmentation->SetSelected(true); this->GetDataStorage()->Add( newSegmentation, toolManager->GetReferenceData(0)); // add as a child, because the segmentation "derives" from the original m_SegC = newSegmentation; auto referencedImages = m_Image->GetData()->GetProperty("files"); m_SegC->GetData()->SetProperty("referenceFiles", referencedImages); } catch (std::bad_alloc) { QMessageBox::warning( nullptr, tr("Create new segmentation"), tr("Could not allocate memory for new segmentation")); } } else { MITK_INFO << "no tools..."; } } void SegmentationReworkView::CleanDicomFolder() { if (m_SegA || m_SegB || m_SegC) { QMessageBox::warning(nullptr, tr("Clean dicom folder"), tr("Please remove the data in data storage before cleaning the download folder")); return; } // std::experimental::filesystem::remove_all(m_DownloadBaseDir); // TODO : use POCO // itk::FileTools::CreateDirectory(m_DownloadBaseDir); } diff --git a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.h b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.h index a3851ae860..cd78ebf922 100644 --- a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.h +++ b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.h @@ -1,108 +1,105 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef SegmentationReworkView_h #define SegmentationReworkView_h #include #include #include "ui_SegmentationReworkViewControls.h" -#include "SegmentationReworkREST.h" -#include #include #include +#include + +#include "ReworkRequestHandler.h" /** \brief SegmentationReworkView \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkAbstractView \ingroup ${plugin_target}_internal */ class SegmentationReworkView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; - void RESTPutCallback(const SegmentationReworkREST::DicomDTO& dto); - void RESTGetCallback(const SegmentationReworkREST::DicomDTO& dto); - void RESTGetCallbackGeneric(const SegmentationReworkREST::DicomDTO& dto); - void UpdateChartWidget(); void ClearChartWidget(); void LoadData(std::vector filePathList); void OnSliderWidgetChanged(double value); void AddProgress(int, QString status); + void UpdateDcmMeta(ReworkRequestHandler::DicomDTO dto); signals: void InvokeLoadData(std::vector filePathList); void InvokeProgress(int, QString status); protected: virtual void CreateQtPartControl(QWidget *parent) override; virtual void SetFocus() override; /// \brief Called when the user clicks the GUI button void CreateNewSegmentationC(); void CleanDicomFolder(); void UploadNewSegmentation(); void RestartConnection(std::string = ""); void OnRestartConnection(); pplx::task TestConnection(); void OnIndividualCheckChange(int state); Ui::SegmentationReworkViewControls m_Controls; private: - std::vector CreateSegmentation(mitk::Image::Pointer baseSegmentation, double threshold); std::string GetAlgorithmOfSegByPath(std::string path); void SetSimilarityGraph(std::vector simScoreArray, int sliceMinStart); - std::unique_ptr m_HttpHandler; - mitk::DICOMWeb* m_DICOMWeb; - mitk::RESTClient* m_RestService; + + mitk::IRESTManager* m_ManagerService; + ReworkRequestHandler* m_RequestHandler; std::string m_CurrentStudyUID; std::string m_SRUID; std::string m_DownloadBaseDir; std::string m_UploadBaseDir; mitk::DataNode::Pointer m_Image; mitk::DataNode::Pointer m_SegA; mitk::DataNode::Pointer m_SegB; mitk::DataNode::Pointer m_SegC; std::map m_ScoreMap; std::string m_GroundTruth; std::string m_thresholdLabel; - QWidget* m_Parent; + QWidget *m_Parent; int counter; }; #endif // SegmentationReworkView_h