diff --git a/Modules/CppRestSdk/include/mitkDICOMWeb.h b/Modules/CppRestSdk/include/mitkDICOMWeb.h index 0b3b27bca1..6f95cebc85 100644 --- a/Modules/CppRestSdk/include/mitkDICOMWeb.h +++ b/Modules/CppRestSdk/include/mitkDICOMWeb.h @@ -1,40 +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 MITKDICOMWEB_H -#define MITKDICOMWEB_H - -#include "MitkCppRestSdkExports.h" - -#include "mitkRESTClient.h" - -namespace mitk -{ - class MITKCPPRESTSDK_EXPORT DICOMWeb : public RESTClient - { - public:; - DICOMWeb(utility::string_t url); - virtual ~DICOMWeb(); - - pplx::task WadoRS(const utility::string_t filePath, std::string studyUID, std::string seriesUID, std::string instanceUID); - pplx::task WadoRS(const utility::string_t folderPath, std::string studyUID, std::string seriesUID); - pplx::task StowRS(utility::string_t filePath, std::string studyUID); - pplx::task QuidoRSInstances(std::map params); - - }; -}; - -#endif // MITKDICOMWEB_H +/*=================================================================== + +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 MITKDICOMWEB_H +#define MITKDICOMWEB_H + +#include "MitkCppRestSdkExports.h" + +#include "mitkRESTClient.h" + +namespace mitk +{ + class MITKCPPRESTSDK_EXPORT DICOMWeb : public RESTClient + { + public: + /** + * @brief Creates a client with the given base URL used to execute DICOMweb requests + * + * @param url the base URL for a PACS implementation like dcm4chee + */ + DICOMWeb(utility::string_t url); + virtual ~DICOMWeb(); + + /** + * @brief Executes a WADO-RS request for a single instance which should be stored to the given filePath. + * The given studyUID, seriesUID, instanceUID defines the requested DICOM object. + * + * @param filePath the path at which the requested file should be stored + * @param studyUID the studyUID of the requested DICOM object + * @param seriesUID the seriesUID of the requested DICOM object + * @param instanceUID the instanceUID of the requested DICOM object + * @return a task to wait for + */ + pplx::task WadoRS(const utility::string_t filePath, + std::string studyUID, + std::string seriesUID, + std::string instanceUID); + + /** + * @brief Executes a WADO-RS request for all instances of a DICOM series which should be stored to the given + * folderPath. The given studyUID, seriesUID, defines the requested DICOM series. + * + * @param folderPath the path at which the requested series of files should be stored + * @param studyUID the studyUID of the requested DICOM object + * @param seriesUID the seriesUID of the requested DICOM object + * @return task to wait for + */ + pplx::task WadoRS(const utility::string_t folderPath, std::string studyUID, std::string seriesUID); + + /** + * @brief Executes a STOW-RS request with a DICOM instance given by the filePath which should be included in the + * study given by the studyUID. * * @param filePath the path at which the file to be stored exists + * @param studyUID the UID of the study at which the DICOM object should be stored + * @return task to wait for + */ + pplx::task StowRS(utility::string_t filePath, std::string studyUID); + + /** + * @brief Execute a QIDO-RS request with the given params on instance level + * + * @param params a map of specific QIDO parameters which filters the instance results + * @return task to wait for with a json response containing filtered instances by the given parameters + */ + pplx::task QidoRSInstances(std::map params); + }; +}; + +#endif // MITKDICOMWEB_H diff --git a/Modules/CppRestSdk/include/mitkRESTClient.h b/Modules/CppRestSdk/include/mitkRESTClient.h index 9b6729073f..47ca6f5f85 100644 --- a/Modules/CppRestSdk/include/mitkRESTClient.h +++ b/Modules/CppRestSdk/include/mitkRESTClient.h @@ -1,61 +1,92 @@ /*=================================================================== 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" #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:; + public: + ; + + /** + * @brief Creates a new client object containing the given base url which is extended by the uri of the member methods + * + * @param url represents the base URL which is extended by the member methods and used as target for HTTP requests + */ RESTClient(utility::string_t url); virtual ~RESTClient(); - pplx::task Post(utility::string_t uri, - utility::string_t contentType, - concurrency::streams::basic_istream fileStream); - + /** + * @brief Executes a HTTP POST request with given uri and the file given by the filePath + * + * @param uri defines the URI which extends the base URL of this object resulting the target of the HTTP request + * @param filePath the path to the file which shall be included in the message body as multipart + * @return task to wait for + */ pplx::task Post(utility::string_t uri, utility::string_t filePath); + + /** + * @brief Executes a HTTP GET request with the given uri and stores the byte stream in a file given by the filePath + * + * @param filePath the file path at which the received byte stream is stored + * @param uri the URI which extends the base URL of this object resulting the target of the HTTP request + * @return task to wait for + */ pplx::task Get(const utility::string_t filePath, utility::string_t uri); - pplx::task Get(utility::string_t uri); + + /** + * @brief Executes a HTTP GET request with the given uri and returns a json object + * + * @param uri the URI which extends the base URL of this object resulting the target of the HTTP request + * @return task with to wait for with resulting json object + */ + pplx::task Get(utility::string_t uri); + + /** + * @brief Executes a HTTP PUT request to the given uri containing the given content json object + * + * @param uri the URI which extends the base URL of this object resulting the target of the HTTP request + * @param content the json body for the PUT request + */ pplx::task PUT(utility::string_t uri, web::json::value content); protected: - MitkClient* m_Client; - + MitkClient *m_Client; }; }; #endif // MITKRESTCLIENT_H diff --git a/Modules/CppRestSdk/include/mitkRESTServer.h b/Modules/CppRestSdk/include/mitkRESTServer.h index 862151aa5c..321bb55673 100644 --- a/Modules/CppRestSdk/include/mitkRESTServer.h +++ b/Modules/CppRestSdk/include/mitkRESTServer.h @@ -1,63 +1,102 @@ /*=================================================================== 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 MITKRESTSERVER_H #define MITKRESTSERVER_H #include #include "cpprest/asyncrt_utils.h" #include "cpprest/containerstream.h" #include "cpprest/filestream.h" #include "cpprest/http_listener.h" #include "cpprest/json.h" #include "cpprest/producerconsumerstream.h" #include "cpprest/uri.h" #include "MitkCppRestSdkExports.h" typedef web::http::experimental::listener::http_listener MitkListener; typedef web::http::http_request MitkRequest; typedef web::http::http_response MitkResponse; typedef web::http::methods MitkRESTMethods; typedef web::http::status_codes MitkRestStatusCodes; typedef web::json::json_exception MitkJsonException; namespace mitk { class MITKCPPRESTSDK_EXPORT RESTServer : public QObject { public: - RESTServer(); + + /** + * @brief Creates an server listening to the given URL + * + * @param url the URL at which the server is listening for requests + */ RESTServer(utility::string_t url); virtual ~RESTServer(); + /** + * @brief Opens the server connection and starts the listening process + * + * @return a task to wait for + */ pplx::task Open() { return m_Listener.open(); } + + /** + * @brief Closes the server connection and closes the listening process + * + * @return a task to wait for + */ pplx::task Close() { return m_Listener.close(); } protected: + + /** + * @brief Handle for incoming GET requests + * + * @param MitkRequest incoming request object + */ virtual void HandleGet(MitkRequest){}; + + /** + * @brief Handle for incoming PUT requests + * + * @param MitkRequest incoming request object + */ virtual void HandlePut(MitkRequest){}; + + /** + * @brief Handle for incoming POST requests + * + * @param MitkRequest incoming request object + */ virtual void HandlePost(MitkRequest){}; + + /** + * @brief Handle for incoming DELETE requests + * + * @param MitkRequest incoming request object + */ virtual void HandleDelete(MitkRequest){}; - void HandleError(pplx::task &t); MitkListener m_Listener; }; }; #endif // MITKRESTSERVER_H diff --git a/Modules/CppRestSdk/include/mitkRESTUtil.h b/Modules/CppRestSdk/include/mitkRESTUtil.h index 24cba4c452..e9d8e596a0 100644 --- a/Modules/CppRestSdk/include/mitkRESTUtil.h +++ b/Modules/CppRestSdk/include/mitkRESTUtil.h @@ -1,38 +1,43 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKRESTUTIL_H #define MITKRESTUTIL_H #include "MitkCppRestSdkExports.h" -#include #include "cpprest/asyncrt_utils.h" +#include namespace mitk { class MITKCPPRESTSDK_EXPORT RESTUtil { - public: + /** + * @brief Converts the given std::wstring into a std::string representation + */ static std::string convertToUtf8(utility::string_t stringT) { return utility::conversions::to_utf8string(stringT); } - static utility::string_t convertToTString(std::string string) { return utility::conversions::to_string_t(string); } + /** + * @brief Converts the given std::string into a std::wstring representation + */ + static utility::string_t convertToTString(std::string string) { return utility::conversions::to_string_t(string); } }; }; #endif // MITKRESTUTIL_H diff --git a/Modules/CppRestSdk/src/mitkDICOMWeb.cpp b/Modules/CppRestSdk/src/mitkDICOMWeb.cpp index 28b2cbe958..5cd68079a9 100644 --- a/Modules/CppRestSdk/src/mitkDICOMWeb.cpp +++ b/Modules/CppRestSdk/src/mitkDICOMWeb.cpp @@ -1,135 +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. ===================================================================*/ #include "mitkDICOMWeb.h" #include "mitkRESTUtil.h" #include mitk::DICOMWeb::DICOMWeb(utility::string_t url) : mitk::RESTClient(url) { } mitk::DICOMWeb::~DICOMWeb() { } -pplx::task mitk::DICOMWeb::QuidoRSInstances(std::map params) +pplx::task mitk::DICOMWeb::QidoRSInstances(std::map params) { MitkUriBuilder queryBuilder(U("rs/instances")); for (auto const& element : params) { queryBuilder.append_query(mitk::RESTUtil::convertToTString(element.first), mitk::RESTUtil::convertToTString(element.second)); } MITK_INFO << utility::conversions::to_utf8string(queryBuilder.to_string()); MitkRequest instances(MitkRESTMethods::GET); instances.set_request_uri(queryBuilder.to_string()); instances.headers().add(U("Accept"), U("application/json")); return m_Client->request(instances).then([=](MitkResponse response) { auto status = response.status_code(); MITK_INFO << " status: " << status; if (status != web::http::status_codes::OK) { MITK_ERROR << "no dicom series found for query " << utility::conversions::to_utf8string(queryBuilder.to_string()); mitkThrow() << "no dicom series found for query " << utility::conversions::to_utf8string(queryBuilder.to_string()); } return response.extract_json().get(); }); } pplx::task mitk::DICOMWeb::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"), mitk::RESTUtil::convertToTString(studyUID)); builder.append_query(U("seriesUID"), mitk::RESTUtil::convertToTString(seriesUID)); builder.append_query(U("objectUID"), mitk::RESTUtil::convertToTString(instanceUID)); builder.append_query(U("contentType"), U("application/dicom")); return Get(filePath, builder.to_string()); } pplx::task mitk::DICOMWeb::WadoRS(const utility::string_t folderPath, std::string studyUID, std::string seriesUID) { typedef std::map ParamMap; ParamMap seriesInstancesParams; seriesInstancesParams.insert(ParamMap::value_type({"StudyInstanceUID"}, studyUID)); seriesInstancesParams.insert(ParamMap::value_type({"SeriesInstanceUID"}, seriesUID)); - return QuidoRSInstances(seriesInstancesParams).then([=](web::json::value jsonResult) -> pplx::task + return QidoRSInstances(seriesInstancesParams).then([=](web::json::value jsonResult) -> pplx::task { auto jsonListResult = jsonResult; auto resultArray = jsonListResult.as_array(); auto firstFileName = std::string(); std::vector> tasks; for (unsigned short i = 0; i < resultArray.size(); i++) { try { auto firstResult = resultArray[i]; auto sopInstanceUIDKey = firstResult.at(U("00080018")); auto sopInstanceObject = sopInstanceUIDKey.as_object(); auto valueKey = sopInstanceObject.at(U("Value")); auto valueArray = valueKey.as_array(); auto sopInstanceUID = valueArray[0].as_string(); auto fileName = utility::string_t(sopInstanceUID).append(U(".dcm")); // save first file name as result to load series if (i == 0) { firstFileName = utility::conversions::to_utf8string(fileName); } auto filePath = utility::string_t(folderPath).append(fileName); auto task = WadoRS(filePath, studyUID, seriesUID, mitk::RESTUtil::convertToUtf8(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)); auto returnTask = joinTask.then([=](void) -> std::string { auto folderPathUtf8 = utility::conversions::to_utf8string(folderPath); auto result = folderPathUtf8 + firstFileName; return result; }); return returnTask; }); } pplx::task mitk::DICOMWeb::StowRS(utility::string_t filePath, std::string studyUID) { // TODO: add data MitkUriBuilder builder(U("rs/studies")); builder.append_path(mitk::RESTUtil::convertToTString(studyUID)); return Post(builder.to_string(), filePath); } \ No newline at end of file diff --git a/Modules/CppRestSdk/src/mitkRESTServer.cpp b/Modules/CppRestSdk/src/mitkRESTServer.cpp index bef1754211..04f4ccdcd7 100644 --- a/Modules/CppRestSdk/src/mitkRESTServer.cpp +++ b/Modules/CppRestSdk/src/mitkRESTServer.cpp @@ -1,37 +1,25 @@ /*=================================================================== 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 "mitkRESTServer.h" #include mitk::RESTServer::RESTServer() {} mitk::RESTServer::RESTServer(utility::string_t url) : m_Listener(url) {} -mitk::RESTServer::~RESTServer() {} - -void mitk::RESTServer::HandleError(pplx::task &t) -{ - try - { - t.get(); - } - catch (...) - { - mitkThrow() << "An error occured."; - } -} \ No newline at end of file +mitk::RESTServer::~RESTServer() {} \ 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 3b642dc761..18225d1543 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,592 +1,592 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "SegmentationReworkView.h" #include // Qt #include #include #include #include #include #include #include #include #include #include #include #include #include const std::string SegmentationReworkView::VIEW_ID = "org.mitk.views.segmentationreworkview"; void SegmentationReworkView::SetFocus() {} void SegmentationReworkView::CreateQtPartControl(QWidget *parent) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); m_Parent = parent; counter = 0; qRegisterMetaType< std::vector >("std::vector"); //m_Controls.verticalWidget->setVisible(false); m_Controls.cleanDicomBtn->setVisible(false); m_Controls.individualWidget_2->setVisible(false); m_Controls.sliderWidget->setMinimum(1); m_Controls.sliderWidget->setMaximum(100); m_Controls.sliderWidget->setTickInterval(1); m_Controls.sliderWidget->setSingleStep(1); m_Controls.radioA->setChecked(true); connect(m_Controls.buttonUpload, &QPushButton::clicked, this, &SegmentationReworkView::UploadNewSegmentation); connect(m_Controls.buttonNewSeg, &QPushButton::clicked, this, &SegmentationReworkView::CreateNewSegmentationC); connect(m_Controls.cleanDicomBtn, &QPushButton::clicked, this, &SegmentationReworkView::CleanDicomFolder); connect(m_Controls.restartConnection, &QPushButton::clicked, this, &SegmentationReworkView::RestartConnection); connect(m_Controls.checkIndiv, &QCheckBox::stateChanged, this, &SegmentationReworkView::OnIndividualCheckChange); connect(m_Controls.sliderWidget, &ctkSliderWidget::valueChanged, this, &SegmentationReworkView::OnSliderWidgetChanged); m_DownloadBaseDir = mitk::IOUtil::GetTempPathA() + "segrework"; MITK_INFO << "using download base dir: " << m_DownloadBaseDir; m_UploadBaseDir = mitk::IOUtil::GetTempPathA() + "uploadSeg"; if (!itksys::SystemTools::FileIsDirectory(m_DownloadBaseDir)) { itk::FileTools::CreateDirectory(m_DownloadBaseDir); } if (!itksys::SystemTools::FileIsDirectory(m_UploadBaseDir)) { itk::FileTools::CreateDirectory(m_UploadBaseDir); } utility::string_t port = U("2020"); utility::string_t address = U("http://127.0.0.1:"); address.append(port); m_HttpHandler = std::unique_ptr(new SegmentationReworkREST(address)); connect(m_HttpHandler.get(), &SegmentationReworkREST::InvokeUpdateChartWidget, this, &SegmentationReworkView::UpdateChartWidget); connect(this, &SegmentationReworkView::InvokeLoadData, this, &SegmentationReworkView::LoadData); connect(this, &SegmentationReworkView::InvokeProgress, this, &SegmentationReworkView::AddProgress); m_HttpHandler->SetPutCallback(std::bind(&SegmentationReworkView::RESTPutCallback, this, std::placeholders::_1)); m_HttpHandler->SetGetImageSegCallback(std::bind(&SegmentationReworkView::RESTGetCallback, this, std::placeholders::_1)); m_HttpHandler->SetGetAddSeriesCallback(std::bind(&SegmentationReworkView::RESTGetCallbackGeneric, this, std::placeholders::_1)); m_HttpHandler->Open().wait(); MITK_INFO << "Listening for requests at: " << utility::conversions::to_utf8string(address); //utility::string_t pacsURL = U("http://jip-dktk/dcm4chee-arc/aets/DCM4CHEE"); utility::string_t pacsURL = U("http://193.174.48.78:8090/dcm4chee-arc/aets/DCM4CHEE"); utility::string_t restURL = U("http://localhost:8000"); m_DICOMWeb = new mitk::DICOMWeb(pacsURL); MITK_INFO << "requests to pacs are sent to: " << utility::conversions::to_utf8string(pacsURL); m_Controls.dcm4cheeURL->setText({ (utility::conversions::to_utf8string(pacsURL).c_str()) }); m_RestService = new mitk::RESTClient(restURL); } void SegmentationReworkView::OnSliderWidgetChanged(double value) { std::map::iterator it; unsigned int count = 0; for (it = m_ScoreMap.begin(); it != m_ScoreMap.end(); it++) { if (it->second < value) { count++; } } QString labelsToDelete = "slices to delete: " + QString::number(count); m_Controls.slicesToDeleteLabel->setText(labelsToDelete); std::map thresholdMap; for (it = m_ScoreMap.begin(); it != m_ScoreMap.end(); it++) { thresholdMap.insert(std::map::value_type(it->first, value)); } m_Controls.chartWidget->RemoveData(m_thresholdLabel); m_Controls.chartWidget->AddData2D(thresholdMap, m_thresholdLabel); m_Controls.chartWidget->SetChartType(m_thresholdLabel, QmitkChartWidget::ChartType::line); m_Controls.chartWidget->Show(); } void SegmentationReworkView::AddProgress(int progress, QString status) { auto futureValue = m_Controls.progressBar->value() + progress; if (futureValue >= 100) { m_Controls.progressBar->setValue(0); m_Controls.progressBar->setFormat(""); } else { m_Controls.progressBar->setFormat(status.append(" %p%")); m_Controls.progressBar->setValue(futureValue); } } void SegmentationReworkView::RestartConnection() { auto host = m_Controls.dcm4cheeHostValue->text(); std::string url = host.toStdString() + "/dcm4chee-arc/aets/DCM4CHEE"; m_DICOMWeb = new mitk::DICOMWeb(utility::conversions::to_string_t(url)); MITK_INFO << "requests to pacs are sent to: " << url; m_Controls.dcm4cheeURL->setText({ (utility::conversions::to_utf8string(url).c_str()) }); } void SegmentationReworkView::OnIndividualCheckChange(int state) { if(state == Qt::Unchecked) { m_Controls.individualWidget_2->setVisible(false); } else if (state == Qt::Checked) { m_Controls.individualWidget_2->setVisible(true); } } void SegmentationReworkView::RESTPutCallback(const SegmentationReworkREST::DicomDTO &dto) { emit InvokeProgress(20, { "display graph and query structured report" }); SetSimilarityGraph(dto.simScoreArray, dto.minSliceStart); m_SRUID = dto.srSeriesUID; m_GroundTruth = dto.groundTruth; typedef std::map ParamMap; ParamMap seriesInstancesParams; seriesInstancesParams.insert((ParamMap::value_type({"StudyInstanceUID"}, dto.studyUID))); seriesInstancesParams.insert((ParamMap::value_type({"SeriesInstanceUID"}, dto.srSeriesUID))); seriesInstancesParams.insert((ParamMap::value_type({"includefield"}, {"0040A375"}))); // Current Requested Procedure Evidence Sequence try { - m_DICOMWeb->QuidoRSInstances(seriesInstancesParams).then([=](web::json::value jsonResult) + m_DICOMWeb->QidoRSInstances(seriesInstancesParams).then([=](web::json::value jsonResult) { auto firstResult = jsonResult[0]; auto actualListKey = firstResult.at(U("0040A375")).as_object().at(U("Value")).as_array()[0].as_object().at(U("00081115")).as_object().at(U("Value")).as_array(); std::string segSeriesUIDA = ""; std::string segSeriesUIDB = ""; std::string imageSeriesUID = ""; for (unsigned int index = 0; index < actualListKey.size(); index++) { auto element = actualListKey[index].as_object(); // get SOP class UID auto innerElement = element.at(U("00081199")).as_object().at(U("Value")).as_array()[0]; auto sopClassUID = innerElement.at(U("00081150")).as_object().at(U("Value")).as_array()[0].as_string(); auto seriesUID = utility::conversions::to_utf8string(element.at(U("0020000E")).as_object().at(U("Value")).as_array()[0].as_string()); if (sopClassUID == U("1.2.840.10008.5.1.4.1.1.66.4")) // SEG { if (segSeriesUIDA.length() == 0) { segSeriesUIDA = seriesUID; } else { segSeriesUIDB = seriesUID; } } else if (sopClassUID == U("1.2.840.10008.5.1.4.1.1.2")) // CT { imageSeriesUID = seriesUID; } } emit InvokeProgress(10, {"load composite context of structured report"}); MITK_INFO << "image series UID " << imageSeriesUID; MITK_INFO << "seg A series UID " << segSeriesUIDA; MITK_INFO << "seg B series UID " << segSeriesUIDB; MITK_INFO << "Load related dicom series ..."; std::string folderPathSeries = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadBaseDir) +"/"; std::string pathSegA = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadBaseDir) + "/"; std::string pathSegB = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadBaseDir) + "/"; auto folderPathSegA = utility::conversions::to_string_t(pathSegA); auto folderPathSegB = utility::conversions::to_string_t(pathSegB); m_CurrentStudyUID = dto.studyUID; std::vector> tasks; auto imageSeriesTask = m_DICOMWeb->WadoRS(utility::conversions::to_string_t(folderPathSeries), dto.studyUID, imageSeriesUID); auto segATask = m_DICOMWeb->WadoRS(folderPathSegA, dto.studyUID, segSeriesUIDA); auto segBTask = m_DICOMWeb->WadoRS(folderPathSegB, dto.studyUID, segSeriesUIDB); tasks.push_back(imageSeriesTask); tasks.push_back(segATask); tasks.push_back(segBTask); auto joinTask = pplx::when_all(begin(tasks), end(tasks)); auto filePathList = joinTask.then([&](std::vector filePathList) { emit InvokeProgress(50, {"load dicom files from disk"}); InvokeLoadData(filePathList); }); }); } catch (mitk::Exception& e) { MITK_ERROR << e.what(); } } void SegmentationReworkView::RESTGetCallbackGeneric(const SegmentationReworkREST::DicomDTO &dto) { std::vector> tasks; if (dto.seriesUIDList.size() > 0) { for (std::string segSeriesUID : dto.seriesUIDList) { std::string folderPathSeries = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadBaseDir) + "/"; try { auto seriesTask = m_DICOMWeb->WadoRS(utility::conversions::to_string_t(folderPathSeries), dto.studyUID, segSeriesUID); tasks.push_back(seriesTask); } catch (const mitk::Exception &exception) { MITK_INFO << exception.what(); return; } } } try { auto joinTask = pplx::when_all(begin(tasks), end(tasks)); auto filePathList = joinTask.then([&](std::vector filePathList) { InvokeLoadData(filePathList); }); } catch (const mitk::Exception& exception) { MITK_INFO << exception.what(); return; } } void SegmentationReworkView::RESTGetCallback(const SegmentationReworkREST::DicomDTO &dto) { std::string folderPathSeries = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadBaseDir) + "/"; MITK_INFO << folderPathSeries; std::string pathSeg = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_DownloadBaseDir) + "/"; auto folderPathSeg = utility::conversions::to_string_t(pathSeg); MITK_INFO << pathSeg; try { std::vector> tasks; auto imageSeriesTask = m_DICOMWeb->WadoRS(utility::conversions::to_string_t(folderPathSeries), dto.studyUID, dto.imageSeriesUID); tasks.push_back(imageSeriesTask); if (dto.seriesUIDList.size() > 0) { for (std::string segSeriesUID : dto.seriesUIDList) { auto segTask = m_DICOMWeb->WadoRS(folderPathSeg, dto.studyUID, segSeriesUID); tasks.push_back(segTask); } } else { auto segATask = m_DICOMWeb->WadoRS(folderPathSeg, dto.studyUID, dto.segSeriesUIDA); tasks.push_back(segATask); } auto joinTask = pplx::when_all(begin(tasks), end(tasks)); auto filePathList = joinTask.then([&](std::vector filePathList) { InvokeLoadData(filePathList); }); } catch (const mitk::Exception &exception) { MITK_INFO << exception.what(); } } std::string SegmentationReworkView::GetAlgorithmOfSegByPath(std::string path) { auto scanner = mitk::DICOMDCMTKTagScanner::New(); mitk::DICOMTagPath algorithmName; algorithmName.AddAnySelection(0x0062, 0x0002).AddElement(0x0062, 0x0009); mitk::StringList files; files.push_back(path); scanner->SetInputFiles(files); scanner->AddTagPath(algorithmName); scanner->Scan(); mitk::DICOMDatasetAccessingImageFrameList frames = scanner->GetFrameInfoList(); auto findings = frames.front()->GetTagValueAsString(algorithmName); if (findings.size() != 0) MITK_INFO << findings.front().value; return findings.front().value; } void SegmentationReworkView::LoadData(std::vector filePathList) { MITK_INFO << "Loading finished. Pushing data to data storage ..."; auto ds = GetDataStorage(); auto dataNodes = mitk::IOUtil::Load(filePathList, *ds); // reinit view mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(ds); // find data nodes m_Image = dataNodes->at(0); m_Image->SetName("image data"); m_SegA = dataNodes->at(1); m_SegB = dataNodes->at(2); auto algorithmNameA = GetAlgorithmOfSegByPath(filePathList[1]); auto algorithmNameB = GetAlgorithmOfSegByPath(filePathList[2]); m_SegA->SetName(algorithmNameA); m_SegB->SetName(algorithmNameB); m_Controls.labelSegAValue->setText(algorithmNameA.c_str()); m_Controls.labelSegBValue->setText(algorithmNameB.c_str()); m_Controls.labelGroundTruthValue->setText(m_GroundTruth.c_str()); emit InvokeProgress(20, { "" }); } void SegmentationReworkView::UpdateChartWidget() { m_Controls.chartWidget->Show(); } void SegmentationReworkView::SetSimilarityGraph(std::vector simScoreArray, int sliceMinStart) { std::string label = "similarity graph"; m_thresholdLabel = "threshold"; //m_Controls.chartWidget->Clear(); double sliceIndex = sliceMinStart; for (double score : simScoreArray) { m_ScoreMap.insert(std::map::value_type(sliceIndex, score)); sliceIndex++; } std::map thresholdMap; m_Controls.chartWidget->AddData2D(m_ScoreMap, label); m_Controls.chartWidget->AddData2D(thresholdMap, m_thresholdLabel); m_Controls.chartWidget->SetChartType(label, QmitkChartWidget::ChartType::line); m_Controls.chartWidget->SetChartType(m_thresholdLabel, QmitkChartWidget::ChartType::line); m_Controls.chartWidget->SetXAxisLabel("slice number"); m_Controls.chartWidget->SetYAxisLabel("similarity in percent"); m_Controls.chartWidget->SetTitle("Similartiy Score for Segmentation Comparison"); } void SegmentationReworkView::UploadNewSegmentation() { AddProgress(10, { "save SEG to temp folder" }); std::string folderPathSeg = mitk::IOUtil::CreateTemporaryDirectory("XXXXXX", m_UploadBaseDir) + "/"; const std::string savePath = folderPathSeg + m_SegC->GetName() + ".dcm"; const std::string mimeType = mitk::MitkDICOMQIIOMimeTypes::DICOMSEG_MIMETYPE_NAME(); mitk::IOUtil::Save(m_SegC->GetData(), mimeType, savePath); // get Series Instance UID from new SEG auto scanner = mitk::DICOMDCMTKTagScanner::New(); mitk::DICOMTagPath seriesUID(0x0020, 0x000E); mitk::StringList files; files.push_back(savePath); scanner->SetInputFiles(files); scanner->AddTagPath(seriesUID); scanner->Scan(); mitk::DICOMDatasetAccessingImageFrameList frames = scanner->GetFrameInfoList(); auto findings = frames.front()->GetTagValueAsString(seriesUID); auto segSeriesUID = findings.front().value; AddProgress(20, {"push SEG to PACS"}); auto filePath = utility::conversions::to_string_t(savePath); try { m_DICOMWeb->StowRS(filePath, m_CurrentStudyUID).then([=] { emit InvokeProgress(40, {"persist reworked SEG to evaluation database"}); MitkUriBuilder queryBuilder(U("tasks/evaluations/")); queryBuilder.append_query(U("srUID"), utility::conversions::to_string_t(m_SRUID)); //queryBuilder.append_path(U("71/")); m_RestService->Get(queryBuilder.to_string()).then([=](web::json::value result) { MITK_INFO << "after GET"; MITK_INFO << utility::conversions::to_utf8string(result.to_string()); auto updatedContent = result.as_array()[0]; updatedContent[U("reworkedSegmentationUID")] = web::json::value::string(utility::conversions::to_string_t(segSeriesUID)); auto id = updatedContent.at(U("id")).as_integer(); MITK_INFO << id; auto idParam = std::to_string(id).append("/"); MitkUriBuilder queryBuilder(U("tasks/evaluations")); queryBuilder.append_path(utility::conversions::to_string_t(idParam)); m_RestService->PUT(queryBuilder.to_string(), updatedContent).then([=](web::json::value result) { MITK_INFO << "successfully stored"; emit InvokeProgress(30, { "successfully stored" }); }); }); }); } catch (const std::exception &exception) { std::cout << exception.what() << std::endl; } } std::vector SegmentationReworkView::CreateSegmentation(mitk::Image::Pointer baseSegmentation, double threshold) { MITK_INFO << "handle individual segmentation creation"; std::map::iterator it; std::vector sliceIndices; unsigned int count = 0; for (it = m_ScoreMap.begin(); it != m_ScoreMap.end(); it++) { if (it->second < threshold) { auto index = it->first; try { mitk::ImagePixelWriteAccessor imageAccessor(baseSegmentation); for (unsigned int x = 0; x < baseSegmentation->GetDimension(0); x++) { for (unsigned int y = 0; y < baseSegmentation->GetDimension(1); y++) { imageAccessor.SetPixelByIndex({ { x, y, int(index) } }, 0); } } } catch (mitk::Exception& e) { MITK_ERROR << e.what(); } count++; sliceIndices.push_back(index); MITK_INFO << "slice " << it->first << " removed "; } } MITK_INFO << "slices deleted " << count; return sliceIndices; } void SegmentationReworkView::CreateNewSegmentationC() { mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); toolManager->InitializeTools(); toolManager->SetReferenceData(m_Image); mitk::Image::Pointer baseImage; if (m_Controls.radioA->isChecked()) { baseImage = dynamic_cast(m_SegA->GetData())->Clone(); } else if (m_Controls.radioB->isChecked()) { baseImage = dynamic_cast(m_SegB->GetData())->Clone(); } if (m_Controls.checkIndiv->isChecked()) { auto sliceIndices = CreateSegmentation(baseImage, m_Controls.sliderWidget->value()); } QmitkNewSegmentationDialog* dialog = new QmitkNewSegmentationDialog(m_Parent); // needs a QWidget as parent, "this" is not QWidget int dialogReturnValue = dialog->exec(); if (dialogReturnValue == QDialog::Rejected) { // user clicked cancel or pressed Esc or something similar return; } // ask the user about an organ type and name, add this information to the image's (!) propertylist // create a new image of the same dimensions and smallest possible pixel type mitk::Tool* firstTool = toolManager->GetToolById(0); if (firstTool) { try { std::string newNodeName = dialog->GetSegmentationName().toStdString(); if (newNodeName.empty()) { newNodeName = "no_name"; } mitk::DataNode::Pointer newSegmentation = firstTool->CreateSegmentationNode(baseImage, newNodeName, dialog->GetColor()); // initialize showVolume to false to prevent recalculating the volume while working on the segmentation newSegmentation->SetProperty("showVolume", mitk::BoolProperty::New(false)); if (!newSegmentation) { return; // could be aborted by user } if (mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetWorkingData(0)) { mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetWorkingData(0)->SetSelected(false); } newSegmentation->SetSelected(true); this->GetDataStorage()->Add(newSegmentation, toolManager->GetReferenceData(0)); // add as a child, because the segmentation "derives" from the original m_SegC = newSegmentation; auto referencedImages = m_Image->GetData()->GetProperty("files"); m_SegC->GetData()->SetProperty("referenceFiles", referencedImages); } catch (std::bad_alloc) { QMessageBox::warning(nullptr, tr("Create new segmentation"), tr("Could not allocate memory for new segmentation")); } } else { MITK_INFO << "no tools..."; } } void SegmentationReworkView::CleanDicomFolder() { if (m_SegA || m_SegB || m_SegC) { QMessageBox::warning(nullptr, tr("Clean dicom folder"), tr("Please remove the data in data storage before cleaning the download folder")); return; } //std::experimental::filesystem::remove_all(m_DownloadBaseDir); // TODO : use POCO //itk::FileTools::CreateDirectory(m_DownloadBaseDir); }