diff --git a/Modules/REST/src/mitkRESTClient.cpp b/Modules/REST/src/mitkRESTClient.cpp index da48c24691..f212cfe78b 100644 --- a/Modules/REST/src/mitkRESTClient.cpp +++ b/Modules/REST/src/mitkRESTClient.cpp @@ -1,212 +1,214 @@ /*=================================================================== 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() { m_ClientConfig.set_validate_certificates(false); } mitk::RESTClient::~RESTClient() {} pplx::task mitk::RESTClient::Get(const web::uri &uri, const std::map headers) { auto client = new http_client(uri, m_ClientConfig); 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) + { MITK_INFO << status; - MITK_INFO << mitk::RESTUtil::convertToUtf8(response.to_string()); - mitkThrow(); - + MITK_INFO << mitk::RESTUtil::convertToUtf8(response.to_string()); + mitkThrow(); + } + auto requestContentType = response.headers().content_type(); if (U("application/json") != requestContentType) response.headers().set_content_type(U("application/json")); return response.extract_json().get(); } catch (std::exception &e) { MITK_INFO << e.what(); mitkThrow() << "Getting response went wrong"; } }); } pplx::task mitk::RESTClient::Get(const web::uri &uri, const utility::string_t &filePath, const std::map headers) { auto client = new http_client(uri, m_ClientConfig); 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, m_ClientConfig); 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 (U("application/json") != requestContentType) response.headers().set_content_type(U("application/json")); return response.extract_json().get(); } catch (std::exception &e) { MITK_INFO << e.what(); mitkThrow() << "Getting response went wrong"; } }); } pplx::task mitk::RESTClient::Post(const web::uri &uri, const std::vector *content, const std::map headers) { auto request = InitRequest(headers); request.set_method(methods::POST); if (nullptr != content) request.set_body(*content); return ExecutePost(uri, request); } pplx::task mitk::RESTClient::Post(const web::uri &uri, const web::json::value *content, const std::map headers) { auto request = InitRequest(headers); request.set_method(methods::POST); if (nullptr != content) request.set_body(*content); return ExecutePost(uri, request); } http_request mitk::RESTClient::InitRequest(const std::map headers) { http_request request; for (auto param : headers) { request.headers().add(param.first, param.second); } return request; } pplx::task mitk::RESTClient::ExecutePost(const web::uri &uri, http_request request) { auto client = new http_client(uri, m_ClientConfig); return client->request(request).then([=](pplx::task responseTask) { try { auto response = responseTask.get(); auto status = response.status_code(); auto requestContentType = response.headers().content_type(); MITK_INFO << status; if (status_codes::OK != status) mitkThrow(); MITK_INFO << mitk::RESTUtil::convertToUtf8(requestContentType); if (U("application/json") != requestContentType) { auto json = web::json::value::object(); json[U("test")] = web::json::value(17); response.set_body(json); // use empty json object in response body to perform return value response.headers().set_content_type(U("application/json")); } return response.extract_json().get(); } catch (std::exception &e) { MITK_INFO << e.what(); mitkThrow() << "Getting response went wrong"; } }); } diff --git a/Plugins/org.mitk.gui.qt.inject/src/internal/InjectView.cpp b/Plugins/org.mitk.gui.qt.inject/src/internal/InjectView.cpp index e4cad879f0..4d6fb12ab5 100644 --- a/Plugins/org.mitk.gui.qt.inject/src/internal/InjectView.cpp +++ b/Plugins/org.mitk.gui.qt.inject/src/internal/InjectView.cpp @@ -1,312 +1,356 @@ /*=================================================================== 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 "InjectView.h" #include #include // Qt #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include const std::string InjectView::VIEW_ID = "org.mitk.views.injectview"; void InjectView::SetFocus() {} void InjectView::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); connect(m_Controls.cleanDicomBtn, &QPushButton::clicked, this, &InjectView::CleanDicomFolder); connect(m_Controls.restartConnection, &QPushButton::clicked, this, &InjectView::OnRestartConnection); connect(m_Controls.testConnection, &QPushButton::clicked, this, &InjectView::TestConnection); connect(m_Controls.saveDICOMBtn, &QPushButton::clicked, this, &InjectView::SaveSelectedDICOMObject); m_DownloadBaseDir = mitk::IOUtil::GetTempPath() + "segInject"; 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(":8080")); } 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 InjectRequestHandler(m_DownloadBaseDir, pacsURL); connect(this, &InjectView::InvokeProgress, this, &InjectView::AddProgress); connect(m_RequestHandler, &InjectRequestHandler::InvokeProgress, this, &InjectView::AddProgress); connect(m_RequestHandler, &InjectRequestHandler::InvokeUpdateDcmMeta, this, &InjectView::InitializeDcmMeta); connect(m_RequestHandler, &InjectRequestHandler::InvokeLoadData, this, &InjectView::LoadData); + // patient image selection predicates + auto isNotAHelperObject = + mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true))); + + 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(isNotAHelperObject, isBinaryPredicate); + mitk::NodePredicateAnd::Pointer isNotABinaryImagePredicate = + mitk::NodePredicateAnd::New(isNotAHelperObject, isNotBinaryPredicate); + + auto isAPatientImagePredicate = mitk::NodePredicateAnd::New( + isNotABinaryImagePredicate, mitk::NodePredicateNot::New(mitk::TNodePredicateDataType::New())); + auto isASegmentationImagePredicate = + mitk::NodePredicateOr::New(isABinaryImagePredicate, mitk::TNodePredicateDataType::New()); + + m_Controls.patImageSelector->SetPredicate(isAPatientImagePredicate); + m_Controls.patImageSelector->SetDataStorage(GetDataStorage()); + m_Controls.segImageSelector->SetPredicate(isASegmentationImagePredicate); + m_Controls.segImageSelector->SetDataStorage(GetDataStorage()); + + // 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; } } // Setup PACS connection RestartConnection(pacsURL); } void InjectView::Activated() { MITK_INFO << "activated"; StartServer(); } void InjectView::Deactivated() { MITK_INFO << "deactivated"; m_ManagerService->HandleDeleteObserver(m_RequestHandler); } void InjectView::Visible() {} void InjectView::Hidden() {} void InjectView::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 InjectView::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 InjectView::InitializeDcmMeta(InjectRequestHandler::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 InjectView::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 InjectView::OnRestartConnection() { RestartConnection(mitk::RESTUtil::convertToTString(m_Controls.dcm4cheeHostValue->text().toStdString())); } void InjectView::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); } } mitk::DataStorage::SetOfObjects::Pointer InjectView::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 InjectView::SaveSelectedDICOMObject() { - auto ds = GetDataStorage(); - auto node = ds->GetAll()->front(); + auto segNode = m_Controls.segImageSelector->GetSelectedNode(); std::string path; - node->GetStringProperty("path", path); + std::string name = mitk::UIDGenerator("", 8).GetUID(); + segNode->GetStringProperty("path", path); + path.append("/").append(name).append(".dcm"); + + MITK_INFO << path; + + // add property + auto imageNode = m_Controls.patImageSelector->GetSelectedNode(); + + auto referencedImages = imageNode->GetData()->GetProperty("files"); + segNode->GetData()->SetProperty("referenceFiles", referencedImages); + + const std::string mimeType = mitk::MitkDICOMQIIOMimeTypes::DICOMSEG_MIMETYPE_NAME(); + mitk::IOUtil::Save(segNode->GetData(), mimeType, path); + emit InvokeProgress(20, {"created new DICOM object locally"}); auto scanner = mitk::DICOMDCMTKTagScanner::New(); mitk::DICOMTagPath studyUID(0x0020, 0x000D); // study UID mitk::StringList files; files.push_back(path); scanner->SetInputFiles(files); scanner->AddTagPath(studyUID); scanner->Scan(); + emit InvokeProgress(10, {"dicom file scanned for tags"}); mitk::DICOMDatasetAccessingImageFrameList frames = scanner->GetFrameInfoList(); auto findings = frames.front()->GetTagValueAsString(studyUID); auto studyUIDValue = findings.front().value; + emit InvokeProgress(10, {"found study uid"}); try { + emit InvokeProgress(30, {"storing DICOM object..."}); m_DicomWeb.SendSTOW(mitk::RESTUtil::convertToTString(path), mitk::RESTUtil::convertToTString(studyUIDValue)) - .then([=] { MITK_INFO << "STOW was successfull"; }); + .then([=] { + emit InvokeProgress(30, {"DICOM object stored."}); + MITK_INFO << "STOW was successfull"; + }); } catch (const std::exception &exception) { std::cout << exception.what() << std::endl; } } void InjectView::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.inject/src/internal/InjectViewControls.ui b/Plugins/org.mitk.gui.qt.inject/src/internal/InjectViewControls.ui index 5cfa964388..ffb6aafc85 100644 --- a/Plugins/org.mitk.gui.qt.inject/src/internal/InjectViewControls.ui +++ b/Plugins/org.mitk.gui.qt.inject/src/internal/InjectViewControls.ui @@ -1,133 +1,162 @@ InjectViewControls 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 - - - + + + + + + + + Patient Image + + + + + + + + + + Segmentation + + + + + + + Save Selected DICOM Object Qt::Vertical QSizePolicy::Expanding 20 220 clean dicom download folder + + + QmitkDataStorageComboBox + QComboBox +
QmitkDataStorageComboBox.h
+
+