diff --git a/Plugins/org.mitk.gui.qt.dicomweb/CMakeLists.txt b/Plugins/org.mitk.gui.qt.dicomweb/CMakeLists.txt index 3c48572708..f12c833178 100644 --- a/Plugins/org.mitk.gui.qt.dicomweb/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.dicomweb/CMakeLists.txt @@ -1,11 +1,13 @@ project(org_mitk_gui_qt_dicomweb) +include_directories(${CTK_INCLUDE_DIRS}) + mitk_create_plugin( - EXPORT_DIRECTIVE DICOMWEB_EXPORT + EXPORT_DIRECTIVE MITK_QT_DICOMWEB EXPORTED_INCLUDE_SUFFIXES src - MODULE_DEPENDS MitkQtWidgetsExt MitkREST MitkRESTService MitkDICOMweb MitkChart MitkSegmentationUI MitkDICOMSegIO - PACKAGE_DEPENDS PUBLIC CTK|CTKWidgets + MODULE_DEPENDS MitkQtWidgetsExt MitkREST MitkRESTService MitkDICOMweb MitkMultilabel MitkDICOMSegIO + PACKAGE_DEPENDS Qt5|OpenGL ) diff --git a/Plugins/org.mitk.gui.qt.dicomweb/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.dicomweb/manifest_headers.cmake index d605fb6d39..5d3ca85ef4 100644 --- a/Plugins/org.mitk.gui.qt.dicomweb/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.dicomweb/manifest_headers.cmake @@ -1,8 +1,5 @@ -set(Plugin-Name "Dicomweb") +set(Plugin-Name "MITK 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 - org.blueberry.ui.qt - ) \ No newline at end of file +set(Require-Plugin org.mitk.gui.qt.common org.mitk.gui.qt.datamanager) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebRequestHandler.cpp b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebRequestHandler.cpp index 55e28c0793..b8b6bc6a73 100644 --- a/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebRequestHandler.cpp +++ b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebRequestHandler.cpp @@ -1,327 +1,335 @@ /*=================================================================== 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/")); + m_DicomWeb = mitk::DICOMweb(pacsURI); +} + +void DicomWebRequestHandler::UpdateDicomWebUrl(utility::string_t pacsURI) { + m_DicomWeb = mitk::DICOMweb(pacsURI); +} + +mitk::DICOMweb DicomWebRequestHandler::DicomWebGet() { + return m_DicomWeb; } 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::POST) { return HandlePost(uri, data, headers); } 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 ..."}); emit InvokeUpdateDcmMeta(dto); // 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::HandlePost(const web::uri &uri, const web::json::value &data, const mitk::RESTUtil::ParamMap &headers) { if (!data.is_null()) // avoid unused warning MITK_INFO << "data was not null"; auto contentType = headers.find(U("Content-Type")); if ((contentType->second.find(U("multipart/form-data")) != std::string::npos) || contentType->second.find(U("multipart/related")) != std::string::npos && contentType->second.find(U("application/dicom")) != std::string::npos) { } MITK_INFO <<"not implemented yet"; auto errorResponse = web::http::http_response(web::http::status_codes::BadRequest); 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 index 3a46f06ba3..1bbe3f5f1b 100644 --- a/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebRequestHandler.h +++ b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebRequestHandler.h @@ -1,84 +1,87 @@ /*=================================================================== 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); + void UpdateDicomWebUrl(utility::string_t pacsURI); + mitk::DICOMweb DicomWebGet(); 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); web::http::http_response HandlePost(const web::uri &uri, const web::json::value &data, const mitk::RESTUtil::ParamMap &headers); 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 index 7090c29f0c..c68212a82c 100644 --- a/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebView.cpp +++ b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebView.cpp @@ -1,438 +1,452 @@ /*=================================================================== 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 "DicomWebView.h" + +#include "mitkLabelSetImage.h" +#include +#include "mitkIOUtil.h" +#include "mitkNodePredicateProperty.h" +#include "mitkImage.h" +#include "mitkNodePredicateDataType.h" #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; + SetPredicates(); + + + + qRegisterMetaType>("std::vector"); qRegisterMetaType>("std::vector"); qRegisterMetaType("DicomDTO"); m_Controls.cleanDicomBtn->setVisible(true); connect(m_Controls.buttonUpload, &QPushButton::clicked, this, &DicomWebView::UploadNewSegmentation); 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.patImageSelector, + SIGNAL(CurrentSelectionChanged(QList)), + this, + SLOT(OnPatientSelectionChanged(QList))); + connect(m_Controls.segImageSelector, + SIGNAL(CurrentSelectionChanged(QList)), + this, + SLOT(OnSegmentationSelectionChanged(QList))); 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://10.128.129.166:8080"); + utility::string_t pacsURL = U("");// e.g. http://10.128.129.166:8080 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::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); + // Should be done last, if everything else is configured because it triggers the autoselection of data. + m_Controls.patImageSelector->SetAutoSelectNewNodes(true); + m_Controls.segImageSelector->SetAutoSelectNewNodes(true); + //RestartConnection(pacsURL); +} + +void DicomWebView::SetPredicates() { + mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); + mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage"); + mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); + mitk::NodePredicateDataType::Pointer isOdf = mitk::NodePredicateDataType::New("OdfImage"); + auto isSegment = mitk::NodePredicateDataType::New("Segment"); + + mitk::NodePredicateOr::Pointer validImages = mitk::NodePredicateOr::New(); + validImages->AddPredicate(mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isSegment))); + validImages->AddPredicate(isDwi); + validImages->AddPredicate(isDti); + validImages->AddPredicate(isOdf); + + m_IsNotAHelperObject = + mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true))); + + m_IsOfTypeImagePredicate = mitk::NodePredicateAnd::New(validImages, m_IsNotAHelperObject); + + mitk::NodePredicateProperty::Pointer isBinaryPredicate = + mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); + mitk::NodePredicateNot::Pointer isNotBinaryPredicate = mitk::NodePredicateNot::New(isBinaryPredicate); + + mitk::NodePredicateAnd::Pointer isABinaryImagePredicate = + mitk::NodePredicateAnd::New(m_IsOfTypeImagePredicate, isBinaryPredicate); + mitk::NodePredicateAnd::Pointer isNotABinaryImagePredicate = + mitk::NodePredicateAnd::New(m_IsOfTypeImagePredicate, isNotBinaryPredicate); + + m_IsASegmentationImagePredicate = + mitk::NodePredicateOr::New(isABinaryImagePredicate, mitk::TNodePredicateDataType::New()); + m_IsAPatientImagePredicate = mitk::NodePredicateAnd::New( + isNotABinaryImagePredicate, mitk::NodePredicateNot::New(mitk::TNodePredicateDataType::New())); + + m_Controls.patImageSelector->SetDataStorage(GetDataStorage()); + m_Controls.patImageSelector->SetNodePredicate(m_IsAPatientImagePredicate); + m_Controls.patImageSelector->SetSelectionIsOptional(false); + m_Controls.patImageSelector->SetInvalidInfo("Select an image."); + m_Controls.patImageSelector->SetPopUpTitel("Select an image."); + m_Controls.patImageSelector->SetPopUpHint( + "Select an image that should be used and could be uploaded."); // TODO: set Image to uplaod + + m_Controls.segImageSelector->SetDataStorage(GetDataStorage()); + m_Controls.segImageSelector->SetNodePredicate(m_IsASegmentationImagePredicate); + m_Controls.segImageSelector->SetSelectionIsOptional(false); + m_Controls.segImageSelector->SetInvalidInfo("Select a segmentation."); + m_Controls.segImageSelector->SetPopUpTitel("Select a segmentation."); + m_Controls.segImageSelector->SetPopUpHint("Select a segmentation that should be uploaded."); } 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) { + return m_RequestHandler->DicomWebGet().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); + m_RequestHandler->UpdateDicomWebUrl(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); } } -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); - emit InvokeProgress(20, {""}); -} 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([=] { + m_RequestHandler->DicomWebGet().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; -} +//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::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 index 1377a819c2..1aaee5aa08 100644 --- a/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebView.h +++ b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebView.h @@ -1,136 +1,135 @@ /*=================================================================== 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 +#include #include "DicomWebRequestHandler.h" #include -#include -#include #include -#include + + + + +#include "ui_DicomWebViewControls.h" +#include "mitkNodePredicateNot.h" +#include "mitkNodePredicateAnd.h" +#include "mitkNodePredicateOr.h" /** @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 +//, public mitk::IRenderWindowPartListener { 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 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; + void SetPredicates(); virtual void SetFocus() override; void CleanDicomFolder(); void UploadNewSegmentation(); void RestartConnection(utility::string_t newHost); void OnRestartConnection(); pplx::task TestConnection(); Ui::DicomWebViewControls m_Controls; + mitk::NodePredicateNot::Pointer m_IsNotAHelperObject; + mitk::NodePredicateAnd::Pointer m_IsOfTypeImagePredicate; + mitk::NodePredicateOr::Pointer m_IsASegmentationImagePredicate; + mitk::NodePredicateAnd::Pointer m_IsAPatientImagePredicate; private: - std::vector CreateSegmentation(mitk::Image::Pointer baseSegmentation, double threshold); + // std::vector CreateSegmentation(mitk::Image::Pointer baseSegmentation, double threshold); - std::string GetAlgorithmOfSegByPath(std::string path); + //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 index d3d3c0e13c..0ace6ea5b6 100644 --- a/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebViewControls.ui +++ b/Plugins/org.mitk.gui.qt.dicomweb/src/internal/DicomWebViewControls.ui @@ -1,131 +1,242 @@ DicomWebViewControls 0 0 - 465 - 868 + 290 + 462 + + + 0 + 0 + + 0 0 QmitkTemplate + + QLayout::SetMinimumSize + - - - - - dcm4chee host - - - - - - - example input: http://193.174.48.78:8090 - - - - - - - 0 - - - Qt::AlignCenter - - - true - - - - - - - - - restart connection - - - - - - - - - - - - - - - - - - - - - Qt::AlignCenter - - - - - - - test connection - - - - - - - - - - - Do image processing + + + + 0 + 0 + - - Upload Segmentation + + + 0 + 0 + + + + 16777215 + 16777215 + + + + + + + dcm4chee host + + + + + + + example input: http://193.174.48.78:8090 + + + + + + + + + restart connection + + + + + + + + + + + + + + Qt::AlignCenter + + + + + + + + + + + + + + + + 0 + + + Qt::AlignCenter + + + true + + + + - - - Qt::Vertical + + + + 0 + 0 + - - QSizePolicy::Expanding + + Data Selection - - - 20 - 220 - - - + + + 6 + + + 6 + + + 6 + + + 6 + + + + + QLayout::SetMinimumSize + + + 4 + + + + + + 0 + 0 + + + + Patient Image + + + + + + + + 0 + 40 + + + + + + + + + 0 + 0 + + + + Segmentation + + + + + + + + 0 + 40 + + + + + + + + + + + 0 + 0 + + clean dicom download folder + + + + + 0 + 0 + + + + Do image processing + + + Upload Segmentation + + + - + + + QmitkSingleNodeSelectionWidget + QWidget +
QmitkSingleNodeSelectionWidget.h
+ 1 +
+
+ + +