diff --git a/Modules/CppRestSdk/include/mitkRESTClient.h b/Modules/CppRestSdk/include/mitkRESTClient.h index fb08ec7495..480cf94025 100644 --- a/Modules/CppRestSdk/include/mitkRESTClient.h +++ b/Modules/CppRestSdk/include/mitkRESTClient.h @@ -1,63 +1,63 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKRESTCLIENT_H #define MITKRESTCLIENT_H #include "cpprest/asyncrt_utils.h" #include "cpprest/containerstream.h" #include "cpprest/filestream.h" #include "cpprest/http_client.h" #include "cpprest/json.h" #include "cpprest/producerconsumerstream.h" #include "cpprest/uri.h" // hm.. maybe go after that warning at some time? seems like a nasty hack, but works so far :) #pragma warning(disable : 4251) #include "MitkCppRestSdkExports.h" typedef web::http::client::http_client MitkClient; typedef web::http::http_request MitkRequest; typedef web::http::http_response MitkResponse; typedef web::http::methods MitkRESTMethods; typedef web::http::uri_builder MitkUriBuilder; typedef web::http::status_codes MitkRestStatusCodes; typedef web::json::json_exception MitkJsonException; namespace mitk { class MITKCPPRESTSDK_EXPORT RESTClient { public:; RESTClient(utility::string_t url); virtual ~RESTClient(); pplx::task Post(utility::string_t uri, - utility::string_t contentType, - concurrency::streams::streambuf data); + utility::string_t contentType, + concurrency::streams::basic_istream fileStream); pplx::task Get(const utility::string_t filePath, utility::string_t uri); pplx::task WadoRS(const utility::string_t filePath, std::string studyUID, std::string seriesUID, std::string instanceUID); pplx::task WadoRS(const utility::string_t filePath, std::string studyUID, std::string seriesUID); pplx::task StowRS(utility::string_t filePath, std::string studyUID); private: MitkClient m_Client; }; }; #endif // MITKRESTCLIENT_H diff --git a/Modules/CppRestSdk/src/mitkRESTClient.cpp b/Modules/CppRestSdk/src/mitkRESTClient.cpp index bedfac0beb..4ba224d3a6 100644 --- a/Modules/CppRestSdk/src/mitkRESTClient.cpp +++ b/Modules/CppRestSdk/src/mitkRESTClient.cpp @@ -1,157 +1,162 @@ /*=================================================================== 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 "mitkRESTClient.h" #include mitk::RESTClient::RESTClient(utility::string_t url) : m_Client(url) { } mitk::RESTClient::~RESTClient() {} pplx::task mitk::RESTClient::Get(utility::string_t filePath, utility::string_t uri) { MITK_DEBUG << "Calling GET with " << utility::conversions::to_utf8string(uri) << " on client " << utility::conversions::to_utf8string(m_Client.base_uri().to_string()) << " save into " << utility::conversions::to_utf8string(filePath); auto fileBuffer = std::make_shared>(); return concurrency::streams::file_buffer::open(filePath, std::ios::out).then([=](concurrency::streams::streambuf outFile) -> pplx::task { *fileBuffer = outFile; return m_Client.request(MitkRESTMethods::GET, uri); }) // Write the response body into the file buffer. .then([=](MitkResponse response) -> pplx::task { MITK_DEBUG << "Status code: " << response.status_code(); return response.body().read_to_end(*fileBuffer); }) // Close the file buffer. .then([=](size_t) { return fileBuffer->close(); }); } pplx::task mitk::RESTClient::Post(utility::string_t uri, utility::string_t contentType, - concurrency::streams::streambuf data) + concurrency::streams::basic_istream fileStream) { MITK_INFO << "Calling POST with " << utility::conversions::to_utf8string(uri) << " on client " << utility::conversions::to_utf8string(m_Client.base_uri().to_string()); MitkRequest postRequest(MitkRESTMethods::POST); postRequest.set_request_uri(uri); postRequest.headers().add(U("Content-Type"), contentType); - postRequest.set_body(data); + postRequest.set_body(fileStream); + + MITK_INFO << fileStream.is_open(); + MITK_INFO << fileStream.is_valid(); + MITK_INFO << fileStream.streambuf().size(); + MITK_INFO << fileStream.streambuf().can_read(); MITK_INFO << "Request: " << utility::conversions::to_utf8string(postRequest.to_string()); - return m_Client.request(postRequest).then([=](MitkResponse response) + return m_Client.request(postRequest).then([fileStream](MitkResponse response) { + fileStream.close(); MITK_INFO << "Response: " << utility::conversions::to_utf8string(response.to_string()); }); } pplx::task mitk::RESTClient::WadoRS(utility::string_t filePath, std::string studyUID, std::string seriesUID, std::string instanceUID) { MitkUriBuilder builder(U("wado")); builder.append_query(U("requestType"), U("WADO")); builder.append_query(U("studyUID"), utility::conversions::to_string_t(studyUID)); builder.append_query(U("seriesUID"), utility::conversions::to_string_t(seriesUID)); builder.append_query(U("objectUID"), utility::conversions::to_string_t(instanceUID)); builder.append_query(U("contentType"), U("application/dicom")); return Get(filePath, builder.to_string()); } pplx::task mitk::RESTClient::WadoRS(const utility::string_t folderPath, std::string studyUID, std::string seriesUID) { // this is actually a quido-rs request, should be packed into a seperate method.. at some time.. //but there are many possible requests to support: http://dicom.nema.org/medical/dicom/current/output/chtml/part18/sect_6.7.html MitkUriBuilder builder(U("rs/instances")); builder.append_query(U("StudyInstanceUID"), utility::conversions::to_string_t(studyUID)); builder.append_query(U("SeriesInstanceUID"), utility::conversions::to_string_t(seriesUID)); MITK_INFO << utility::conversions::to_utf8string(builder.to_string()); MitkRequest getSeries(MitkRESTMethods::GET); getSeries.set_request_uri(builder.to_string()); getSeries.headers().add(U("Accept"), U("application/json")); return m_Client.request(getSeries).then([=](MitkResponse response) -> pplx::task { MITK_INFO << "search for instances in series with uid " << seriesUID << " status: " << response.status_code(); auto jsonListResult = response.extract_json().get(); auto resultArray = jsonListResult.as_array(); auto firstFileName = std::string(); std::vector> tasks; for (unsigned short i = 0; i < resultArray.size(); i++) { try { auto firstResult = resultArray[i]; auto sopInstanceUIDKey = firstResult.at(U("00080018")); auto sopInstanceObject = sopInstanceUIDKey.as_object(); auto valueKey = sopInstanceObject.at(U("Value")); auto valueArray = valueKey.as_array(); auto sopInstanceUID = valueArray[0].as_string(); auto fileName = utility::string_t(sopInstanceUID).append(U(".dcm")); // save first file name as result to load series if (i == 0) { firstFileName = utility::conversions::to_utf8string(fileName); } auto filePath = utility::string_t(folderPath).append(fileName); auto task = WadoRS(filePath, studyUID, seriesUID, utility::conversions::to_utf8string(sopInstanceUID)); tasks.push_back(task); } catch (const web::json::json_exception& e) { MITK_ERROR << e.what(); } } auto joinTask = pplx::when_all(begin(tasks), end(tasks)); return joinTask.then([=](void) { return utility::conversions::to_utf8string(folderPath).append(firstFileName); }); }); } pplx::task mitk::RESTClient::StowRS(utility::string_t filePath, std::string studyUID) { // TODO: add data MitkUriBuilder builder(U("rs/studies")); builder.append_path(utility::conversions::to_string_t(studyUID)); - return concurrency::streams::file_buffer::open(filePath, std::ios::in) - .then([=](concurrency::streams::streambuf data) { - return Post(builder.to_string(), U("multipart/related; type='application/dicom';"), data); - }); + return concurrency::streams::file_stream::open_istream(filePath).then([=](concurrency::streams::basic_istream fileStream) { + return Post(builder.to_string(), U("multipart/related; type='application/dicom';"), fileStream); + }); } \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.cpp b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.cpp index a7bb73fb57..290f45cdd7 100644 --- a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.cpp @@ -1,186 +1,202 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "SegmentationReworkView.h" // Qt #include #include +#include // uuid class +#include // generators +#include +#include +#include + const std::string SegmentationReworkView::VIEW_ID = "org.mitk.views.segmentationreworkview"; void SegmentationReworkView::SetFocus() {} void SegmentationReworkView::CreateQtPartControl(QWidget *parent) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); qRegisterMetaType< std::vector >("std::vector"); connect(m_Controls.buttonUpload, &QPushButton::clicked, this, &SegmentationReworkView::UploadNewSegmentation); utility::string_t port = U("2020"); utility::string_t address = U("http://127.0.0.1:"); address.append(port); m_HttpHandler = std::unique_ptr(new SegmentationReworkREST(address)); connect(m_HttpHandler.get(), &SegmentationReworkREST::InvokeUpdateChartWidget, this, &SegmentationReworkView::UpdateChartWidget); connect(this, &SegmentationReworkView::InvokeLoadData, this, &SegmentationReworkView::LoadData); m_HttpHandler->SetPutCallback(std::bind(&SegmentationReworkView::RESTPutCallback, this, std::placeholders::_1)); m_HttpHandler->Open().wait(); MITK_INFO << "Listening for requests at: " << utility::conversions::to_utf8string(address); utility::string_t pacsHost = U("http://193.174.48.78:8090/dcm4chee-arc/aets/DCM4CHEE"); m_RestClient = new mitk::RESTClient(pacsHost); } void SegmentationReworkView::RESTPutCallback(const SegmentationReworkREST::DicomDTO &dto) { SetSimilarityGraph(dto.simScoreArray, dto.minSliceStart); MITK_INFO << "Load related dicom series ..."; - std::string folderPathSeries = "/temp/downloadSeries/"; - auto folderPathSegA = U("/temp/segA/"); - auto folderPathSegB = U("/temp/segB/"); + boost::uuids::random_generator generator; + + std::string folderPathSeries = m_downloadBaseDir + boost::uuids::to_string(generator()) + "/"; + std::experimental::filesystem::create_directory(folderPathSeries); + + std::string pathSegA = m_downloadBaseDir + boost::uuids::to_string(generator()) + "/"; + std::string pathSegB = m_downloadBaseDir + boost::uuids::to_string(generator()) + "/"; + + auto folderPathSegA = utility::conversions::to_string_t(pathSegA); + auto folderPathSegB = utility::conversions::to_string_t(pathSegB); + + std::experimental::filesystem::create_directory(pathSegA); + std::experimental::filesystem::create_directory(pathSegB); m_CurrentStudyUID = dto.studyUID; std::vector> tasks; auto imageSeriesTask = m_RestClient->WadoRS(utility::conversions::to_string_t(folderPathSeries), dto.studyUID, dto.imageSeriesUID); auto segATask = m_RestClient->WadoRS(folderPathSegA, dto.studyUID, dto.segSeriesUIDA); auto segBTask = m_RestClient->WadoRS(folderPathSegB, dto.studyUID, dto.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) { InvokeLoadData(filePathList); }); } void SegmentationReworkView::LoadData(std::vector filePathList) { MITK_INFO << "Loading finished. Pushing data to data storage ..."; - mitk::IOUtil::Load(filePathList, *this->GetDataStorage()); + auto ds = GetDataStorage(); + mitk::IOUtil::Load(filePathList, *ds); + // reinit view + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(ds); } void SegmentationReworkView::UpdateChartWidget() { m_Controls.chartWidget->Show(); } void SegmentationReworkView::SetSimilarityGraph(std::vector simScoreArray, int sliceMinStart) { std::map map; double sliceIndex = sliceMinStart; for (double score : simScoreArray) { map.insert(std::map::value_type(sliceIndex, score)); sliceIndex++; } m_Controls.chartWidget->AddData2D(map, "similarity score"); m_Controls.chartWidget->SetChartType("similarity score", QmitkChartWidget::ChartType::line); m_Controls.chartWidget->SetXAxisLabel("slice number"); m_Controls.chartWidget->SetYAxisLabel("similarity score"); } void SegmentationReworkView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, const QList &nodes) { // iterate all selected objects, adjust warning visibility foreach(mitk::DataNode::Pointer node, nodes) { if (node.IsNotNull() && dynamic_cast(node->GetData())) { m_Controls.labelWarning->setVisible(false); return; } } m_Controls.labelWarning->setVisible(true); } void SegmentationReworkView::UploadNewSegmentation() { - auto filePath = U("/temp/segA/1.2.276.0.7230010.3.1.4.296485376.8.1533635734.141264.dcm"); + auto filePath = U("1.2.276.0.7230010.3.1.4.296485376.8.1533635734.141264.dcm"); m_CurrentStudyUID = "1.2.840.113654.2.70.1.159145727925405623564217141386659468090"; try { - m_RestClient->StowRS(filePath, m_CurrentStudyUID).then([] - { - MITK_INFO << "SEG uploaded"; - }); + m_RestClient->StowRS(filePath, m_CurrentStudyUID).wait(); } - catch (std::exception &exception) + catch (const std::exception &exception) { - MITK_ERROR << exception.what(); + std::cout << exception.what() << std::endl; } } void SegmentationReworkView::DoImageProcessing() { QList nodes = this->GetDataManagerSelection(); if (nodes.empty()) return; mitk::DataNode *node = nodes.front(); if (!node) { // Nothing selected. Inform the user and return QMessageBox::information(nullptr, "Template", "Please load and select an image before starting image processing."); return; } // here we have a valid mitk::DataNode // a node itself is not very useful, we need its data item (the image) mitk::BaseData *data = node->GetData(); if (data) { // test if this data item is an image or not (could also be a surface or something totally different) mitk::Image *image = dynamic_cast(data); if (image) { std::stringstream message; std::string name; message << "Performing image processing for image "; if (node->GetName(name)) { // a property called "name" was found for this DataNode message << "'" << name << "'"; } message << "."; MITK_INFO << message.str(); // actually do something here... } } } diff --git a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.h b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.h index 8a8f5bfca4..efe5ce3c73 100644 --- a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.h +++ b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkView.h @@ -1,80 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef SegmentationReworkView_h #define SegmentationReworkView_h #include #include #include "ui_SegmentationReworkViewControls.h" #include "SegmentationReworkRest.h" #include /** \brief SegmentationReworkView \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkAbstractView \ingroup ${plugin_target}_internal */ class SegmentationReworkView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; void RESTPutCallback(const SegmentationReworkREST::DicomDTO& dto); void UpdateChartWidget(); void LoadData(std::vector filePathList); signals: void InvokeLoadData(std::vector filePathList); protected: virtual void CreateQtPartControl(QWidget *parent) override; virtual void SetFocus() override; /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer source, const QList &nodes) override; /// \brief Called when the user clicks the GUI button void DoImageProcessing(); void UploadNewSegmentation(); Ui::SegmentationReworkViewControls m_Controls; private: void SetSimilarityGraph(std::vector simScoreArray, int sliceMinStart); std::unique_ptr m_HttpHandler; mitk::RESTClient* m_RestClient; std::string m_CurrentStudyUID; + // use filesystem::path later... + std::string m_downloadBaseDir = "/temp/"; }; #endif // SegmentationReworkView_h