diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake
index ff2ccda265..a0a195b026 100644
--- a/Plugins/PluginList.cmake
+++ b/Plugins/PluginList.cmake
@@ -1,93 +1,94 @@
# 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.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.ext:OFF
org.mitk.gui.qt.extapplication:OFF
org.mitk.gui.qt.common:ON
org.mitk.gui.qt.stdmultiwidgeteditor:ON
org.mitk.gui.qt.mxnmultiwidgeteditor:OFF
org.mitk.gui.qt.common.legacy:OFF
org.mitk.gui.qt.cmdlinemodules:OFF
org.mitk.gui.qt.chartExample: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.dicomweb: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.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.ultrasoundtrackingnavigation: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.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.dicomweb/CMakeLists.txt b/Plugins/org.mitk.gui.qt.dicomweb/CMakeLists.txt
new file mode 100644
index 0000000000..3c48572708
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/CMakeLists.txt
@@ -0,0 +1,11 @@
+project(org_mitk_gui_qt_dicomweb)
+
+mitk_create_plugin(
+ EXPORT_DIRECTIVE DICOMWEB_EXPORT
+ EXPORTED_INCLUDE_SUFFIXES src
+ MODULE_DEPENDS MitkQtWidgetsExt MitkREST MitkRESTService MitkDICOMweb MitkChart MitkSegmentationUI MitkDICOMSegIO
+ PACKAGE_DEPENDS PUBLIC CTK|CTKWidgets
+)
+
+
+
diff --git a/Plugins/org.mitk.gui.qt.dicomweb/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.dicomweb/documentation/UserManual/Manual.dox
new file mode 100644
index 0000000000..88f9845d05
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/documentation/UserManual/Manual.dox
@@ -0,0 +1,17 @@
+/**
+\page org_mitk_gui_qt_dicomweb The Dicomweb
+
+\imageMacro{icon.png,"Icon of Dicomweb",2.00}
+
+\tableofcontents
+
+\section org_mitk_gui_qt_dicomwebOverview Overview
+Describe the features of your awesome plugin here
+
+- Increases productivity
+
- Creates beautiful images
+
- Generates PhD thesis
+
- Brings world peace
+
+
+*/
diff --git a/Plugins/org.mitk.gui.qt.dicomweb/documentation/UserManual/icon.xpm b/Plugins/org.mitk.gui.qt.dicomweb/documentation/UserManual/icon.xpm
new file mode 100644
index 0000000000..9057c20bc6
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/documentation/UserManual/icon.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * icon_xpm[] = {
+"16 16 2 1",
+" c #FF0000",
+". c #000000",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/Plugins/org.mitk.gui.qt.dicomweb/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.dicomweb/documentation/doxygen/modules.dox
new file mode 100644
index 0000000000..4d75a140d0
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/documentation/doxygen/modules.dox
@@ -0,0 +1,16 @@
+/**
+ \defgroup org_mitk_gui_qt_dicomweb org.mitk.gui.qt.dicomweb
+ \ingroup MITKPlugins
+
+ \brief Describe your plugin here.
+
+*/
+
+/**
+ \defgroup org_mitk_gui_qt_dicomweb_internal Internal
+ \ingroup org_mitk_gui_qt_dicomweb
+
+ \brief This subcategory includes the internal classes of the org.mitk.gui.qt.dicomweb plugin. Other
+ plugins must not rely on these classes. They contain implementation details and their interface
+ may change at any time. We mean it.
+*/
diff --git a/Plugins/org.mitk.gui.qt.dicomweb/files.cmake b/Plugins/org.mitk.gui.qt.dicomweb/files.cmake
new file mode 100644
index 0000000000..66150a0db7
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/files.cmake
@@ -0,0 +1,44 @@
+set(SRC_CPP_FILES
+
+)
+
+set(INTERNAL_CPP_FILES
+ org_mitk_gui_qt_dicomweb_Activator.cpp
+ DicomWebView.cpp
+ DicomWebRequestHandler.cpp
+)
+
+set(UI_FILES
+ src/internal/DicomWebViewControls.ui
+)
+
+set(MOC_H_FILES
+ src/internal/org_mitk_gui_qt_dicomweb_Activator.h
+ src/internal/DicomWebView.h
+ src/internal/DicomWebRequestHandler.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
+ 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.dicomweb/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.dicomweb/manifest_headers.cmake
new file mode 100644
index 0000000000..3b91ca1325
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/manifest_headers.cmake
@@ -0,0 +1,5 @@
+set(Plugin-Name "Dicomweb")
+set(Plugin-Version "0.1")
+set(Plugin-Vendor "German Cancer Research Center (DKFZ)")
+set(Plugin-ContactAddress "http://www.mitk.org")
+set(Require-Plugin org.mitk.gui.qt.common)
diff --git a/Plugins/org.mitk.gui.qt.dicomweb/plugin.xml b/Plugins/org.mitk.gui.qt.dicomweb/plugin.xml
new file mode 100644
index 0000000000..dd0fcafd25
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/plugin.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
diff --git a/Plugins/org.mitk.gui.qt.dicomweb/resources/icon.xpm b/Plugins/org.mitk.gui.qt.dicomweb/resources/icon.xpm
new file mode 100644
index 0000000000..9057c20bc6
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/resources/icon.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * icon_xpm[] = {
+"16 16 2 1",
+" c #FF0000",
+". c #000000",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebRequestHandler.cpp b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebRequestHandler.cpp
new file mode 100644
index 0000000000..2857617820
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebRequestHandler.cpp
@@ -0,0 +1,303 @@
+/*===================================================================
+
+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 "DicomWebRequestHandler.h"
+
+#include
+#include
+#include
+
+US_INITIALIZE_MODULE
+
+DicomWebRequestHandler::DicomWebRequestHandler() {}
+
+DicomWebRequestHandler::DicomWebRequestHandler(std::string downloadDir, utility::string_t pacsURI)
+ : m_DownloadDir{downloadDir}
+{
+ m_DicomWeb = mitk::DICOMweb(pacsURI + U("/dcm4chee-arc/aets/DCM4CHEE/"));
+}
+
+DicomWebRequestHandler::DicomDTO DicomWebRequestHandler::ExtractDTO(const web::json::value &data)
+{
+ DicomDTO dto;
+ auto messageTypeKey = data.at(U("messageType"));
+ if (messageTypeKey.as_string() == U("downloadData"))
+ {
+ MITK_INFO << "within extract dto";
+
+ auto imageStudyUIDKey = data.at(U("studyUID"));
+ auto srSeriesUIDKey = data.at(U("srSeriesUID"));
+
+ auto groundTruthKey = data.at(U("groundTruth"));
+
+ auto simScoreKey = data.at(U("simScoreArray"));
+ auto minSliceStartKey = data.at(U("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::http::http_response DicomWebRequestHandler::Notify(const web::uri &uri,
+ const web::json::value &data,
+ const web::http::method &method,
+ const mitk::RESTUtil::ParamMap &headers)
+{
+ headers.size();
+
+ MITK_INFO << "Incoming notify";
+ if (method == web::http::methods::GET)
+ {
+ return HandleGet(uri, data);
+ }
+ else if (method == web::http::methods::PUT)
+ {
+ return HandlePut(uri, data);
+ }
+ else if (method == web::http::methods::OPTIONS)
+ {
+ return HandleOptions(uri, data);
+ }
+
+ web::http::http_response response(web::http::status_codes::BadGateway);
+ response.set_body(U("No one can handle http method from request")); // TODO: include method name
+ return response;
+}
+
+web::http::http_response DicomWebRequestHandler::HandlePut(const web::uri &uri, const web::json::value &data)
+{
+ if (uri.to_string() != U("/inject")) // avoid unused warning
+ MITK_INFO << "no inject path";
+
+ emit InvokeProgress(20, {"display graph and query structured report"});
+
+ if (data == web::json::value())
+ {
+ MITK_INFO << "no data in body";
+ web::http::http_response response(web::http::status_codes::BadRequest);
+ response.set_body(U("No data in body of request")); // TODO: include method name
+ return response;
+ }
+ MITK_INFO << mitk::RESTUtil::convertToUtf8(data.serialize());
+ DicomDTO dto = ExtractDTO(data);
+ MITK_INFO << mitk::RESTUtil::convertToUtf8(dto.imageSeriesUID);
+
+ emit InvokeSimilarityGraph(dto.simScoreArray, dto.minSliceStart);
+ emit InvokeUpdateDcmMeta(dto);
+
+ mitk::RESTUtil::ParamMap seriesInstancesParams;
+
+ seriesInstancesParams.insert(mitk::RESTUtil::ParamMap::value_type(U("StudyInstanceUID"), dto.studyUID));
+ seriesInstancesParams.insert(mitk::RESTUtil::ParamMap::value_type(U("SeriesInstanceUID"), dto.srSeriesUID));
+ seriesInstancesParams.insert(
+ mitk::RESTUtil::ParamMap::value_type(U("includefield"),
+ U("0040A375"))); // Current Requested Procedure Evidence Sequence
+ try
+ {
+ MITK_INFO << "send qido request";
+ m_DicomWeb.SendQIDO(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();
+
+ MITK_INFO << "received qido response";
+ 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(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 = 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 " << 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 =
+ m_DicomWeb.SendWADO(utility::conversions::to_string_t(folderPathSeries), dto.studyUID, imageSeriesUID);
+ auto segATask = m_DicomWeb.SendWADO(folderPathSegA, dto.studyUID, segSeriesUIDA);
+ auto segBTask = m_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 InvokeLoadDataSegDicomWeb(filePathList);
+ });
+ });
+ }
+ catch (mitk::Exception &e)
+ {
+ MITK_ERROR << e.what();
+ }
+ web::http::http_response response(web::http::status_codes::InternalError);
+ response.set_body(U("Something went wrong while processing the request.")); // TODO: include method name
+ return response;
+}
+
+web::http::http_response DicomWebRequestHandler::HandleGet(const web::uri &uri, const web::json::value &data)
+{
+ if (!data.is_null()) // avoid unused warning
+ MITK_INFO << "data was not null";
+
+ auto query = web::uri(uri).query();
+ auto httpParams = web::uri::split_query(query);
+
+ // IHE Invoke Image Display style
+ auto requestType = httpParams.find(U("requestType"));
+
+ auto errorResponse = web::http::http_response(web::http::status_codes::BadRequest);
+
+ if (requestType != httpParams.end())
+ {
+ if (requestType->second == U("LOAD_SERIES"))
+ {
+ // data extraction
+ DicomDTO dto;
+ dto.studyUID = httpParams.at(U("studyUID"));
+ auto seriesUIDList = httpParams.at(U("seriesUIDList"));
+ auto seriesUIDListUtf8 = mitk::RESTUtil::convertToUtf8(seriesUIDList);
+ std::istringstream f(seriesUIDListUtf8);
+ std::string s;
+ while (getline(f, s, ','))
+ {
+ dto.seriesUIDList.push_back(mitk::RESTUtil::convertToTString(s));
+ }
+ emit InvokeProgress(20, {"incoming series request ..."});
+ // tasks
+ std::vector> tasks;
+
+ if (dto.seriesUIDList.size() > 0)
+ {
+ for (auto segSeriesUID : dto.seriesUIDList)
+ {
+ utility::string_t folderPathSeries =
+ utility::conversions::to_string_t(mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadDir) + "/");
+
+ try
+ {
+ auto seriesTask = m_DicomWeb.SendWADO(folderPathSeries, dto.studyUID, segSeriesUID);
+ tasks.push_back(seriesTask);
+ }
+ catch (const mitk::Exception &exception)
+ {
+ MITK_INFO << exception.what();
+ return errorResponse;
+ }
+ }
+ }
+ emit InvokeProgress(40, {"download series ..."});
+ try
+ {
+ auto joinTask = pplx::when_all(begin(tasks), end(tasks));
+ auto filePathList = joinTask.then([&](std::vector filePathList) {
+ emit InvokeLoadData(filePathList);
+ emit InvokeProgress(40, {""});
+ });
+ }
+ catch (const mitk::Exception &exception)
+ {
+ MITK_INFO << exception.what();
+ return errorResponse;
+ }
+ }
+ }
+ else
+ {
+ MITK_INFO << "no requestType parameter was provided";
+ }
+
+ return errorResponse;
+}
+
+web::http::http_response DicomWebRequestHandler::HandleOptions(const web::uri &uri, const web::json::value &data)
+{
+ if (uri.to_string() != U("/inject")) // avoid unused warning
+ MITK_INFO << "no inject path";
+
+ if (!data.is_null()) // avoid unused warning
+ MITK_INFO << "data was not null";
+
+ MITK_INFO << "OPTIONS incoming";
+
+ web::http::http_response response(web::http::status_codes::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"), "http://localhost:8002");
+
+ return response;
+}
\ No newline at end of file
diff --git a/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebRequestHandler.h b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebRequestHandler.h
new file mode 100644
index 0000000000..c49b6b2709
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebRequestHandler.h
@@ -0,0 +1,81 @@
+/*===================================================================
+
+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 DicomWebRequestHandler_h
+#define DicomWebRequestHandler_h
+
+#include
+#include
+#include
+#include
+
+/**
+ * @brief This class represents the http message handler for the segmentation DicomWeb.
+ */
+class DicomWebRequestHandler : 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;
+ };
+
+ DicomWebRequestHandler();
+
+ /**
+ * Creates the request handler for segmentation DicomWeb. The received data is stored into the given download dir.
+ *
+ * @param downloadDir the directory to which received data is stored.
+ */
+ DicomWebRequestHandler(std::string downloadDir, utility::string_t pacsURI);
+
+ /**
+ * Overrides IRESTObserver::Notify. Here arrive the incoming messages.
+ */
+ web::http::http_response Notify(const web::uri &uri,
+ const web::json::value &data,
+ const web::http::method &method,
+ const mitk::RESTUtil::ParamMap &headers);
+
+signals:
+ void InvokeProgress(int, QString status);
+ void InvokeSimilarityGraph(std::vector score, int sliceStart);
+ void InvokeUpdateDcmMeta(DicomDTO dto);
+ void InvokeLoadData(std::vector);
+ void InvokeLoadDataSegDicomWeb(std::vector);
+
+private:
+ DicomDTO ExtractDTO(const web::json::value &data);
+ web::http::http_response HandlePut(const web::uri &uri, const web::json::value &data);
+ web::http::http_response HandleGet(const web::uri &uri, const web::json::value &data);
+ web::http::http_response HandleOptions(const web::uri &uri, const web::json::value &data);
+
+ std::string m_DownloadDir;
+ mitk::DICOMweb m_DicomWeb;
+};
+
+#endif // DicomWebRequestHandler_h
diff --git a/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebView.cpp b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebView.cpp
new file mode 100644
index 0000000000..dd6bbbd09e
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebView.cpp
@@ -0,0 +1,590 @@
+/*===================================================================
+
+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 "DicomWebView.h"
+
+#include
+#include
+
+// Qt
+#include
+#include
+
+// mitk
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+const std::string DicomWebView::VIEW_ID = "org.mitk.views.dicomwebview";
+
+void DicomWebView::SetFocus() {}
+
+void DicomWebView::CreateQtPartControl(QWidget *parent)
+{
+ // create GUI widgets from the Qt Designer's .ui file
+ m_Controls.setupUi(parent);
+ m_Parent = parent;
+
+ qRegisterMetaType>("std::vector");
+ qRegisterMetaType>("std::vector");
+ qRegisterMetaType("DicomDTO");
+
+ m_Controls.cleanDicomBtn->setVisible(true);
+ 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, &DicomWebView::UploadNewSegmentation);
+ connect(m_Controls.buttonNewSeg, &QPushButton::clicked, this, &DicomWebView::CreateNewSegmentationC);
+ connect(m_Controls.cleanDicomBtn, &QPushButton::clicked, this, &DicomWebView::CleanDicomFolder);
+ connect(m_Controls.restartConnection, &QPushButton::clicked, this, &DicomWebView::OnRestartConnection);
+ connect(m_Controls.testConnection, &QPushButton::clicked, this, &DicomWebView::TestConnection);
+ connect(m_Controls.checkIndiv, &QCheckBox::stateChanged, this, &DicomWebView::OnIndividualCheckChange);
+ connect(
+ m_Controls.sliderWidget, &ctkSliderWidget::valueChanged, this, &DicomWebView::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);
+ }
+
+ m_HostURL = U("http://localhost");
+ auto host = m_HostURL;
+ auto envHostURL = std::getenv("HOST_URL");
+ if (envHostURL)
+ {
+ MITK_INFO << "host url " << std::string(envHostURL);
+ m_HostURL = mitk::RESTUtil::convertToTString(std::string(envHostURL));
+ host = m_HostURL;
+ }
+ else
+ {
+ host = host.append(U(":8000"));
+ }
+
+ m_restURL = host.append(U("/rest-srs"));
+ MITK_INFO << "rest url: " << mitk::RESTUtil::convertToUtf8(m_restURL);
+ utility::string_t pacsURL = U("http://193.174.48.78:8090");
+ auto envPacsURL = std::getenv("PACS_URL");
+
+ if (envPacsURL)
+ {
+ pacsURL = mitk::RESTUtil::convertToTString(std::string(envPacsURL));
+ }
+
+ m_RequestHandler = new DicomWebRequestHandler(m_DownloadBaseDir, pacsURL);
+
+ connect(this, &DicomWebView::InvokeProgress, this, &DicomWebView::AddProgress);
+ connect(m_RequestHandler, &DicomWebRequestHandler::InvokeProgress, this, &DicomWebView::AddProgress);
+ connect(
+ m_RequestHandler, &DicomWebRequestHandler::InvokeSimilarityGraph, this, &DicomWebView::SetSimilarityGraph);
+ connect(
+ m_RequestHandler, &DicomWebRequestHandler::InvokeUpdateDcmMeta, this, &DicomWebView::InitializeDcmMeta);
+ connect(m_RequestHandler, &DicomWebRequestHandler::InvokeLoadData, this, &DicomWebView::LoadData);
+ connect(
+ m_RequestHandler, &DicomWebRequestHandler::InvokeLoadDataSegDicomWeb, this, &DicomWebView::LoadDataSegDicomWeb);
+
+ // Get the micro service
+ us::ModuleContext *context = us::ModuleRegistry::GetModule(1)->GetModuleContext();
+ auto managerRef = context->GetServiceReference();
+ if (managerRef)
+ {
+ auto managerService = context->GetService(managerRef);
+ if (managerService)
+ {
+ m_ManagerService = managerService;
+ }
+ }
+
+ RestartConnection(pacsURL);
+}
+
+void DicomWebView::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 DicomWebView::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 DicomWebView::InitializeDcmMeta(DicomWebRequestHandler::DicomDTO dto)
+{
+ m_CurrentStudyUID = mitk::RESTUtil::convertToUtf8(dto.studyUID);
+ m_SRUID = mitk::RESTUtil::convertToUtf8(dto.srSeriesUID);
+ m_GroundTruth = mitk::RESTUtil::convertToUtf8(dto.groundTruth);
+}
+
+void DicomWebView::Activated()
+{
+ StartServer();
+ MITK_INFO << "activated";
+}
+
+void DicomWebView::Deactivated()
+{
+ MITK_INFO << "deactivated";
+ m_ManagerService->HandleDeleteObserver(m_RequestHandler);
+}
+
+void DicomWebView::Visible()
+{
+ MITK_INFO << "visible";
+}
+
+void DicomWebView::Hidden()
+{
+ MITK_INFO << "hidden";
+}
+
+pplx::task DicomWebView::TestConnection()
+{
+ mitk::RESTUtil::ParamMap seriesInstancesParams;
+
+ seriesInstancesParams.insert(mitk::RESTUtil::ParamMap::value_type(U("limit"), U("1")));
+ m_Controls.connectionStatus->setText(QString("Testing connection ..."));
+
+ return m_DicomWeb.SendQIDO(seriesInstancesParams).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 DicomWebView::OnRestartConnection()
+{
+ RestartConnection(mitk::RESTUtil::convertToTString(m_Controls.dcm4cheeHostValue->text().toStdString()));
+}
+
+void DicomWebView::RestartConnection(utility::string_t newHost)
+{
+ utility::string_t host;
+ if (newHost.empty())
+ {
+ MITK_INFO << "Host was empty";
+ m_Controls.connectionStatus->setText(QString("Host must not be empty!"));
+ return;
+ }
+
+ utility::string_t url = newHost + U("/dcm4chee-arc/aets/DCM4CHEE/");
+
+ MITK_INFO << "Restarting connection to " << mitk::RESTUtil::convertToUtf8(url) << " ...";
+ m_Controls.connectionStatus->setText(QString("Restarting connection..."));
+ m_Controls.dcm4cheeURL->setText({(utility::conversions::to_utf8string(url).c_str())});
+
+ m_DicomWeb = mitk::DICOMweb(url);
+
+ 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: " << mitk::RESTUtil::convertToUtf8(url);
+ }
+}
+
+void DicomWebView::OnIndividualCheckChange(int state)
+{
+ if (state == Qt::Unchecked)
+ {
+ m_Controls.individualWidget_2->setVisible(false);
+ }
+ else if (state == Qt::Checked)
+ {
+ m_Controls.individualWidget_2->setVisible(true);
+ }
+}
+
+std::string DicomWebView::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;
+}
+
+mitk::DataStorage::SetOfObjects::Pointer DicomWebView::LoadData(std::vector filePathList)
+{
+ MITK_INFO << "Pushing data to data storage ...";
+ auto ds = GetDataStorage();
+ auto dataNodes = mitk::IOUtil::Load(filePathList, *ds);
+ // reinit view
+ mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(ds);
+ return dataNodes;
+}
+
+void DicomWebView::LoadDataSegDicomWeb(std::vector filePathList)
+{
+ auto dataNodes = LoadData(filePathList);
+
+ // 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 DicomWebView::SetSimilarityGraph(std::vector simScoreArray, int sliceMinStart)
+{
+ std::string label = "similarity graph";
+ m_thresholdLabel = "threshold";
+
+ 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");
+ m_Controls.chartWidget->Show();
+}
+
+void DicomWebView::StartServer()
+{
+ utility::string_t path = U("/inject");
+
+ auto pathEnv = std::getenv("SERVER_PATH");
+ if (pathEnv)
+ {
+ path = mitk::RESTUtil::convertToTString(std::string(pathEnv));
+ }
+
+ utility::string_t port = U(":4040");
+ utility::string_t address = U("http://+");
+ if (m_HostURL == U("http://localhost"))
+ address = m_HostURL;
+
+ address.append(port);
+ address.append(path);
+ // Setup listening server
+ m_ManagerService->ReceiveRequest(address, m_RequestHandler);
+ MITK_INFO << "Listening for requests at: " << utility::conversions::to_utf8string(address);
+}
+
+void DicomWebView::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::MitkDICOMSEGIOMimeTypes::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.SendSTOW(filePath, mitk::RESTUtil::convertToTString(m_CurrentStudyUID)).then([=] {
+ emit InvokeProgress(50, {"persist reworked SEG to evaluation database"});
+
+ mitk::DICOMweb::MitkUriBuilder queryBuilder(m_restURL + U("/tasks/evaluations/"));
+ queryBuilder.append_query(U("srUID"), utility::conversions::to_string_t(m_SRUID));
+
+ m_ManagerService->SendRequest(queryBuilder.to_uri(), mitk::IRESTManager::RequestType::Get)
+ .then([=](web::json::value result) {
+ MITK_INFO << "after GET";
+ MITK_INFO << utility::conversions::to_utf8string(result.serialize());
+ 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("/");
+
+ mitk::DICOMweb::MitkUriBuilder queryBuilder(m_restURL + U("/tasks/evaluations"));
+ queryBuilder.append_path(utility::conversions::to_string_t(idParam));
+
+ m_ManagerService->SendJSONRequest(queryBuilder.to_uri(), mitk::IRESTManager::RequestType::Put, &updatedContent)
+ .then([=](web::json::value result) {
+ MITK_INFO << utility::conversions::to_utf8string(result.serialize());
+ if (result[U("reworkedSegmentationUID")].as_string() == utility::conversions::to_string_t(segSeriesUID))
+ {
+ MITK_INFO << "successfully stored";
+ emit InvokeProgress(30, {"successfully stored"});
+ }
+ });
+ });
+ });
+ }
+ catch (const std::exception &exception)
+ {
+ std::cout << exception.what() << std::endl;
+ }
+}
+
+std::vector DicomWebView::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 DicomWebView::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);
+
+ 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 DicomWebView::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;
+ }
+
+ auto downloadDir = Poco::File(m_DownloadBaseDir);
+ downloadDir.remove(true);
+}
diff --git a/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebView.h b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebView.h
new file mode 100644
index 0000000000..7588237c22
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebView.h
@@ -0,0 +1,148 @@
+/*===================================================================
+
+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 DicomWebView_h
+#define DicomWebView_h
+
+#include
+
+#include
+
+#include "ui_DicomWebViewControls.h"
+
+#include "DicomWebRequestHandler.h"
+#include
+#include
+#include
+#include
+#include
+
+/**
+ @brief DicomWebView
+
+ This class represents the view to make connections to a PACS server and show some information to do a manual DicomWeb
+ upon two existing segmentation volumes.
+
+ \sa QmitkAbstractView
+ \ingroup ${plugin_target}_internal
+*/
+class DicomWebView : public QmitkAbstractView, public mitk::ILifecycleAwarePart
+{
+ Q_OBJECT
+
+public:
+ static const std::string VIEW_ID;
+
+ /**
+ * @brief Loads the files given by a list of file paths.
+ *
+ * @param filePathList a list of absolute file paths
+ * @return set of objects containing the newly loaded data nodes
+ */
+ mitk::DataStorage::SetOfObjects::Pointer LoadData(std::vector filePathList);
+
+ /**
+ * @brief Loads the files given by a list of file paths. This method expects exactly three items in the list (image
+ * series, seg series a, seg series b). Additional information for segmentation DicomWeb is displayed.
+ *
+ *
+ * @param filePathList a list of absolute file paths
+ */
+ void LoadDataSegDicomWeb(std::vector filePathList);
+
+ /**
+ * @brief Calculates how many slices would be delete if the given threshold would be applied to the segmentation
+ * volume. The information about the segmentation similarity is used and slices below the threshold are to be
+ * discarded. Updates the display.
+ *
+ * @param value the threshold value (between 0 and 1).
+ */
+ void OnSliderWidgetChanged(double value);
+
+ /**
+ * @brief Progress is added to the progressbar in a percent value and the given status is displayed. The progress will
+ * not exceed 100 points.
+ *
+ * @param progress the progress in percent points to be added to the bar
+ * @param status the status to be displayed after achieving the progress
+ */
+ void AddProgress(int progress, QString status);
+
+ /**
+ * @brief Initializes the DICOM meta data used by this view.
+ *
+ * @param dto the data transfer object for received DICOM meta data.
+ */
+ void InitializeDcmMeta(DicomWebRequestHandler::DicomDTO dto);
+
+ virtual void Activated() override;
+ virtual void Deactivated() override;
+ virtual void Visible() override;
+ virtual void Hidden() override;
+
+signals:
+ void InvokeProgress(int, QString status);
+
+protected:
+ virtual void CreateQtPartControl(QWidget *parent) override;
+
+ virtual void SetFocus() override;
+
+ void CreateNewSegmentationC();
+
+ void CleanDicomFolder();
+ void UploadNewSegmentation();
+ void RestartConnection(utility::string_t newHost);
+ void OnRestartConnection();
+ pplx::task TestConnection();
+ void OnIndividualCheckChange(int state);
+
+ Ui::DicomWebViewControls 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);
+
+ void StartServer();
+
+ mitk::IRESTManager *m_ManagerService;
+ DicomWebRequestHandler *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;
+ mitk::DICOMweb m_DicomWeb;
+
+ QWidget *m_Parent;
+
+ utility::string_t m_restURL;
+ utility::string_t m_HostURL;
+};
+
+#endif // DicomWebView_h
diff --git a/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebViewControls.ui b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebViewControls.ui
new file mode 100644
index 0000000000..0a63bb7d9f
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebViewControls.ui
@@ -0,0 +1,313 @@
+
+
+ DicomWebViewControls
+
+
+
+ 0
+ 0
+ 465
+ 868
+
+
+
+
+ 0
+ 0
+
+
+
+ QmitkTemplate
+
+
+ -
+
+
-
+
+
+ dcm4chee host
+
+
+
+ -
+
+
+ example input: http://193.174.48.78:8090
+
+
+
+ -
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ restart connection
+
+
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
-
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ test connection
+
+
+
+
+
+
+
+ -
+
+
+
-
+
+
-
+
+
+ Segmentation B:
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ Segmentation A:
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ Ground Truth:
+
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 400
+
+
+
+
+ 16777215
+ 400
+
+
+
+
+ -
+
+
+ false
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 60
+
+
+
+ Select segmentation basis
+
+
+ true
+
+
+
+ QLayout::SetDefaultConstraint
+
+
-
+
+
+ A
+
+
+
+ -
+
+
+ B
+
+
+
+ -
+
+
+ Individual
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
-
+
+
+ Slices to delete:
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+ Create new Segmentation
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Do image processing
+
+
+ Upload Segmentation
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Expanding
+
+
+
+ 20
+ 220
+
+
+
+
+ -
+
+
+ clean dicom download folder
+
+
+
+
+
+
+
+
+ QmitkChartWidget
+ QWidget
+
+ 1
+
+
+ ctkSliderWidget
+ QWidget
+
+ 1
+
+
+
+
+
diff --git a/Plugins/org.mitk.gui.qt.dicomweb/src/internal/org_mitk_gui_qt_dicomweb_Activator.cpp b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/org_mitk_gui_qt_dicomweb_Activator.cpp
new file mode 100644
index 0000000000..c0e7b0af27
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/org_mitk_gui_qt_dicomweb_Activator.cpp
@@ -0,0 +1,25 @@
+/*============================================================================
+
+The Medical Imaging Interaction Toolkit (MITK)
+
+Copyright (c) German Cancer Research Center (DKFZ)
+All rights reserved.
+
+Use of this source code is governed by a 3-clause BSD license that can be
+found in the LICENSE file.
+
+============================================================================*/
+
+
+#include "org_mitk_gui_qt_dicomweb_Activator.h"
+#include "DicomWebView.h"
+
+namespace mitk
+{
+ void org_mitk_gui_qt_dicomweb_Activator::start(ctkPluginContext *context)
+ {
+ BERRY_REGISTER_EXTENSION_CLASS(DicomWebView, context)
+ }
+
+ void org_mitk_gui_qt_dicomweb_Activator::stop(ctkPluginContext *context) { Q_UNUSED(context) }
+}
diff --git a/Plugins/org.mitk.gui.qt.dicomweb/src/internal/org_mitk_gui_qt_dicomweb_Activator.h b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/org_mitk_gui_qt_dicomweb_Activator.h
new file mode 100644
index 0000000000..5e5ee5555c
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/org_mitk_gui_qt_dicomweb_Activator.h
@@ -0,0 +1,34 @@
+/*============================================================================
+
+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 org_mitk_gui_qt_dicomweb_Activator_h
+#define org_mitk_gui_qt_dicomweb_Activator_h
+
+#include
+
+namespace mitk
+{
+ class org_mitk_gui_qt_dicomweb_Activator : public QObject, public ctkPluginActivator
+ {
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_dicomweb")
+ Q_INTERFACES(ctkPluginActivator)
+
+ public:
+ void start(ctkPluginContext *context);
+ void stop(ctkPluginContext *context);
+
+ }; // org_mitk_gui_qt_dicomweb_Activator
+}
+
+#endif // org_mitk_gui_qt_dicomweb_Activator_h