diff --git a/Modules/Chart/src/QmitkChartWidget.cpp b/Modules/Chart/src/QmitkChartWidget.cpp index 802dfa301a..a668da9d81 100644 --- a/Modules/Chart/src/QmitkChartWidget.cpp +++ b/Modules/Chart/src/QmitkChartWidget.cpp @@ -1,520 +1,524 @@ /*=================================================================== 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 #include #include "mitkExceptionMacro.h" #include #include class CustomPage : public QWebEnginePage { public: CustomPage(QObject* parent = 0) : QWebEnginePage(parent) {} virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID) { - MITK_INFO << "JS > " << lineNumber << ": " << message.toStdString(); + if (level == 1) + { + + } + MITK_INFO << "JS > " << lineNumber << ": " << message.toStdString() << " | sourceID: " << sourceID.toStdString(); } }; class QmitkChartWidget::Impl final { public: explicit Impl(QWidget *parent); ~Impl(); Impl(const Impl &) = delete; Impl &operator=(const Impl &) = delete; void AddData1D(const std::vector &data1D, const std::string &label, QmitkChartWidget::ChartType chartType); void AddData2D(const std::map &data2D, const std::string &label, QmitkChartWidget::ChartType chartType); void RemoveData(const std::string &label); void ClearData(); void SetColor(const std::string &label, const std::string &colorName); void SetLineStyle(const std::string &label, LineStyle style); void SetYAxisScale(AxisScale scale); void SetXAxisLabel(const std::string &label); void SetYAxisLabel(const std::string &label); void SetTitle(const std::string &title); void SetChartType(QmitkChartWidget::ChartType chartType); void SetChartTypeByLabel(const std::string &label, QmitkChartWidget::ChartType chartType); void SetLegendPosition(LegendPosition position); void SetShowLegend(bool show); void SetStackedData(bool stacked); void Show(bool showSubChart); void SetShowDataPoints(bool showDataPoints = false); std::string ConvertChartTypeToString(QmitkChartWidget::ChartType chartType) const; void ClearJavaScriptChart(); void InitializeJavaScriptChart(); void CallJavaScriptFuntion(const QString &command); private: using ChartxyDataVector = std::vector>; std::string GetUniqueLabelName(const QList &labelList, const std::string &label) const; QmitkChartxyData *GetDataElementByLabel(const std::string &label) const; QList GetDataLabels(const ChartxyDataVector &c3xyData) const; void MapTypes(); QWebChannel *m_WebChannel; QWebEngineView *m_WebEngineView; QmitkChartData m_C3Data; ChartxyDataVector m_C3xyData; std::map m_ChartTypeToName; std::map m_LegendPositionToName; std::map m_LineStyleToName; std::map m_AxisScaleToName; }; QmitkChartWidget::Impl::Impl(QWidget *parent) : m_WebChannel(new QWebChannel(parent)), m_WebEngineView(new QWebEngineView(parent)) { // disable context menu for QWebEngineView m_WebEngineView->setContextMenuPolicy(Qt::NoContextMenu); m_WebEngineView->setPage(new CustomPage()); // Set the webengineview to an initial empty page. The actual chart will be loaded once the data is calculated. m_WebEngineView->setUrl(QUrl(QStringLiteral("qrc:///C3js/empty.html"))); m_WebEngineView->page()->setWebChannel(m_WebChannel); m_WebEngineView->settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, false); connect(m_WebEngineView, SIGNAL(loadFinished(bool)), parent, SLOT(OnLoadFinished(bool))); auto layout = new QGridLayout(parent); layout->setMargin(0); layout->addWidget(m_WebEngineView); parent->setLayout(layout); m_ChartTypeToName.emplace(ChartType::bar, "bar"); m_ChartTypeToName.emplace(ChartType::line, "line"); m_ChartTypeToName.emplace(ChartType::spline, "spline"); m_ChartTypeToName.emplace(ChartType::pie, "pie"); m_ChartTypeToName.emplace(ChartType::area, "area"); m_ChartTypeToName.emplace(ChartType::area_spline, "area-spline"); m_ChartTypeToName.emplace(ChartType::scatter, "scatter"); m_LegendPositionToName.emplace(LegendPosition::bottom, "bottom"); m_LegendPositionToName.emplace(LegendPosition::right, "right"); m_LegendPositionToName.emplace(LegendPosition::inset, "inset"); m_LineStyleToName.emplace(LineStyle::solid, "solid"); m_LineStyleToName.emplace(LineStyle::dashed, "dashed"); m_AxisScaleToName.emplace(AxisScale::linear, ""); m_AxisScaleToName.emplace(AxisScale::log, "log"); } QmitkChartWidget::Impl::~Impl() {} std::string CheckForCorrectHex(const std::string &colorName) { std::regex rgx("([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})"); std::smatch match; if (!colorName.empty() && colorName.at(0) != '#' && std::regex_search(colorName.begin(), colorName.end(), match, rgx)) { return "#" + colorName; } else { return colorName; } } void QmitkChartWidget::Impl::AddData1D(const std::vector &data1D, const std::string &label, QmitkChartWidget::ChartType chartType) { std::map transformedData2D; unsigned int count = 0; // transform the 1D data to 2D data for (const auto &ele : data1D) { transformedData2D[count] = ele; count++; } AddData2D(transformedData2D, label, chartType); } void QmitkChartWidget::Impl::AddData2D(const std::map &data2D, const std::string &label, QmitkChartWidget::ChartType chartType) { QMap data2DConverted; for (const auto &aValue : data2D) { data2DConverted.insert(aValue.first, aValue.second); } const std::string chartTypeName(m_ChartTypeToName.at(chartType)); auto definedLabels = GetDataLabels(m_C3xyData); auto uniqueLabel = GetUniqueLabelName(definedLabels, label); if (chartType == ChartType::scatter) { SetShowDataPoints(true); MITK_INFO << "Enabling data points for all because of scatter plot"; } m_C3xyData.push_back(std::make_unique( data2DConverted, QVariant(QString::fromStdString(uniqueLabel)), QVariant(QString::fromStdString(chartTypeName)))); } void QmitkChartWidget::Impl::RemoveData(const std::string &label) { for (ChartxyDataVector::iterator iter = m_C3xyData.begin(); iter != m_C3xyData.end(); ++iter) { if ((*iter)->GetLabel().toString().toStdString() == label) { m_C3xyData.erase(iter); return; } } throw std::invalid_argument("Cannot Remove Data because the label does not exist."); } void QmitkChartWidget::Impl::ClearData() { for (auto &xyData : m_C3xyData) { m_WebChannel->deregisterObject(xyData.get()); } m_C3xyData.clear(); } void QmitkChartWidget::Impl::SetColor(const std::string &label, const std::string &colorName) { auto element = GetDataElementByLabel(label); if (element) { auto colorChecked = CheckForCorrectHex(colorName); element->SetColor(QVariant(QString::fromStdString(colorName))); } } void QmitkChartWidget::Impl::SetLineStyle(const std::string &label, LineStyle style) { auto element = GetDataElementByLabel(label); // only has effect with chart type line if (element && element->GetChartType() == QVariant(QString::fromStdString(ConvertChartTypeToString(ChartType::line)))) { const std::string lineStyleName(m_LineStyleToName.at(style)); element->SetLineStyle(QVariant(QString::fromStdString(lineStyleName))); } } void QmitkChartWidget::Impl::SetYAxisScale(AxisScale scale) { const std::string axisScaleName(m_AxisScaleToName.at(scale)); m_C3Data.SetYAxisScale(QString::fromStdString(axisScaleName)); } void QmitkChartWidget::Impl::SetXAxisLabel(const std::string &label) { m_C3Data.SetXAxisLabel(QString::fromStdString(label)); } void QmitkChartWidget::Impl::SetYAxisLabel(const std::string &label) { m_C3Data.SetYAxisLabel(QString::fromStdString(label)); } void QmitkChartWidget::Impl::SetTitle(const std::string &title) { m_C3Data.SetTitle(QString::fromStdString(title)); } void QmitkChartWidget::Impl::SetChartType(QmitkChartWidget::ChartType chartType) { for (auto iterator = m_C3xyData.begin(); iterator != m_C3xyData.end(); ++iterator) { SetChartTypeByLabel((*iterator)->GetLabel().toString().toStdString(), chartType); } auto chartTypeName = ConvertChartTypeToString(chartType); const QString command = QString::fromStdString("transformView('" + chartTypeName + "')"); CallJavaScriptFuntion(command); } void QmitkChartWidget::Impl::SetChartTypeByLabel(const std::string &label, QmitkChartWidget::ChartType chartType) { auto element = GetDataElementByLabel(label); if (element) { if (chartType == ChartType::scatter) { SetShowDataPoints(true); MITK_INFO << "Enabling data points for all because of scatter plot"; } auto chartTypeName = ConvertChartTypeToString(chartType); element->SetChartType(QVariant(QString::fromStdString(chartTypeName))); } } void QmitkChartWidget::Impl::SetLegendPosition(QmitkChartWidget::LegendPosition legendPosition) { const std::string legendPositionName(m_LegendPositionToName.at(legendPosition)); m_C3Data.SetLegendPosition(QString::fromStdString(legendPositionName)); } void QmitkChartWidget::Impl::SetShowLegend(bool show) { m_C3Data.SetShowLegend(show); } void QmitkChartWidget::Impl::SetStackedData(bool stacked) { m_C3Data.SetStackedData(stacked); } void QmitkChartWidget::Impl::Show(bool showSubChart) { if (m_C3xyData.empty()) { mitkThrow() << "no data available for display in chart"; } m_C3Data.SetAppearance(showSubChart, m_C3xyData.front()->GetChartType() == QVariant("pie")); InitializeJavaScriptChart(); } void QmitkChartWidget::Impl::SetShowDataPoints(bool showDataPoints) { if (showDataPoints == true) { m_C3Data.SetDataPointSize(3); } else { m_C3Data.SetDataPointSize(0); } } std::string QmitkChartWidget::Impl::ConvertChartTypeToString(QmitkChartWidget::ChartType chartType) const { return m_ChartTypeToName.at(chartType); } void QmitkChartWidget::Impl::ClearJavaScriptChart() { m_WebEngineView->setUrl(QUrl(QStringLiteral("qrc:///C3js/empty.html"))); } void QmitkChartWidget::Impl::InitializeJavaScriptChart() { m_WebChannel->registerObject(QStringLiteral("chartData"), &m_C3Data); unsigned count = 0; for (auto &xyData : m_C3xyData) { QString variableName = "xyData" + QString::number(count); m_WebChannel->registerObject(variableName, xyData.get()); count++; } m_WebEngineView->load(QUrl(QStringLiteral("qrc:///C3js/QmitkChartWidget.html"))); } void QmitkChartWidget::Impl::CallJavaScriptFuntion(const QString &command) { m_WebEngineView->page()->runJavaScript(command); } std::string QmitkChartWidget::Impl::GetUniqueLabelName(const QList &labelList, const std::string &label) const { QString currentLabel = QString::fromStdString(label); int counter = 0; while (labelList.contains(currentLabel)) { currentLabel = QString::fromStdString(label + std::to_string(counter)); counter++; } return currentLabel.toStdString(); } QmitkChartxyData *QmitkChartWidget::Impl::GetDataElementByLabel(const std::string &label) const { for (const auto &qmitkChartxyData : m_C3xyData) { if (qmitkChartxyData->GetLabel().toString() == label.c_str()) { return qmitkChartxyData.get(); } } MITK_WARN << "label " << label << " not found in QmitkChartWidget"; return nullptr; } QList QmitkChartWidget::Impl::GetDataLabels(const ChartxyDataVector &c3xyData) const { QList dataLabels; for (auto element = c3xyData.begin(); element != c3xyData.end(); ++element) { dataLabels.push_back((*element)->GetLabel()); } return dataLabels; } QmitkChartWidget::QmitkChartWidget(QWidget *parent) : QWidget(parent), m_Impl(new Impl(this)) {} QmitkChartWidget::~QmitkChartWidget() {} void QmitkChartWidget::AddData1D(const std::vector &data1D, const std::string &label, ChartType type) { m_Impl->AddData1D(data1D, label, type); } void QmitkChartWidget::AddData2D(const std::map &data2D, const std::string &label, ChartType type) { m_Impl->AddData2D(data2D, label, type); } void QmitkChartWidget::RemoveData(const std::string &label) { m_Impl->RemoveData(label); } void QmitkChartWidget::SetColor(const std::string &label, const std::string &colorName) { m_Impl->SetColor(label, colorName); } void QmitkChartWidget::SetLineStyle(const std::string &label, LineStyle style) { m_Impl->SetLineStyle(label, style); } void QmitkChartWidget::SetYAxisScale(AxisScale scale) { m_Impl->SetYAxisScale(scale); } void QmitkChartWidget::SetXAxisLabel(const std::string &label) { m_Impl->SetXAxisLabel(label); } void QmitkChartWidget::SetYAxisLabel(const std::string &label) { m_Impl->SetYAxisLabel(label); } void QmitkChartWidget::SetTitle(const std::string &title) { m_Impl->SetTitle(title); } void QmitkChartWidget::SetChartTypeForAllDataAndReload(ChartType type) { m_Impl->SetChartType(type); } void QmitkChartWidget::SetChartType(const std::string &label, ChartType type) { m_Impl->SetChartTypeByLabel(label, type); } void QmitkChartWidget::SetLegendPosition(LegendPosition position) { m_Impl->SetLegendPosition(position); } void QmitkChartWidget::SetShowLegend(bool show) { m_Impl->SetShowLegend(show); } void QmitkChartWidget::SetStackedData(bool stacked) { m_Impl->SetStackedData(stacked); } void QmitkChartWidget::Show(bool showSubChart) { m_Impl->Show(showSubChart); } void QmitkChartWidget::SetShowDataPoints(bool showDataPoints) { m_Impl->SetShowDataPoints(showDataPoints); } void QmitkChartWidget::Clear() { m_Impl->ClearData(); m_Impl->ClearJavaScriptChart(); } void QmitkChartWidget::OnLoadFinished(bool isLoadSuccessful) { if (isLoadSuccessful) { emit PageSuccessfullyLoaded(); } } void QmitkChartWidget::SetTheme(ChartStyle themeEnabled) { QString command; if (themeEnabled == ChartStyle::darkstyle) { command = QString("changeTheme('dark')"); } else { command = QString("changeTheme('light')"); } m_Impl->CallJavaScriptFuntion(command); } void QmitkChartWidget::Reload(bool showSubChart) { QString subChartString; if (showSubChart) { subChartString = "true"; } else { subChartString = "false"; } const QString command = QString("ReloadChart(" + subChartString + ")"); m_Impl->CallJavaScriptFuntion(command); } diff --git a/Modules/CppRestSdk/src/mitkDICOMWeb.cpp b/Modules/CppRestSdk/src/mitkDICOMWeb.cpp index ce566ac2dd..394a476df3 100644 --- a/Modules/CppRestSdk/src/mitkDICOMWeb.cpp +++ b/Modules/CppRestSdk/src/mitkDICOMWeb.cpp @@ -1,143 +1,151 @@ /*=================================================================== 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(utility::string_t url) : mitk::RESTClient(url) {} -mitk::DICOMWeb::~DICOMWeb() -{ -} +mitk::DICOMWeb::~DICOMWeb() {} pplx::task mitk::DICOMWeb::QidoRSInstances(std::map params) { MitkUriBuilder queryBuilder(U("rs/instances")); - for (auto const& element : params) + for (auto const &element : params) { - queryBuilder.append_query(mitk::RESTUtil::convertToTString(element.first), mitk::RESTUtil::convertToTString(element.second)); + queryBuilder.append_query(mitk::RESTUtil::convertToTString(element.first), + mitk::RESTUtil::convertToTString(element.second)); } MITK_INFO << GetHost() << "/" << 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([=](pplx::task taskResponse) - { + return m_Client->request(instances).then([=](pplx::task taskResponse) { try { MitkResponse response = taskResponse.get(); 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()); + 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(); + if (response.headers()[L"Content-Type"] == L"application/dicom+json") + { + response.headers().remove(U("Content-Type")); + response.headers().add(U("Content-Type"), U("application/json")); } + + return response.extract_json().get(); + } catch (std::exception &e) { mitkThrow() << e.what(); } }); } -pplx::task mitk::DICOMWeb::WadoRS(utility::string_t filePath, std::string studyUID, std::string seriesUID, std::string instanceUID) +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) +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 QidoRSInstances(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) + 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 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/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.cpp b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.cpp index c5432c1bc8..b5c8141676 100644 --- a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.cpp @@ -1,196 +1,220 @@ /*=================================================================== 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 "SegmentationReworkREST.h" #include #include SegmentationReworkREST::SegmentationReworkREST() {} SegmentationReworkREST::SegmentationReworkREST(utility::string_t url) : mitk::RESTServer(url) { m_Listener.support(MitkRESTMethods::PUT, std::bind(&SegmentationReworkREST::HandlePut, this, std::placeholders::_1)); m_Listener.support(MitkRESTMethods::GET, std::bind(&SegmentationReworkREST::HandleGet, this, std::placeholders::_1)); + m_Listener.support(MitkRESTMethods::OPTIONS, std::bind(&SegmentationReworkREST::HandleOptions, this, std::placeholders::_1)); } SegmentationReworkREST::~SegmentationReworkREST() {} -void SegmentationReworkREST::HandleGet(MitkRequest message) +void SegmentationReworkREST::HandleOptions(MitkRequest message) +{ + auto messageString = message.to_string(); + MITK_INFO << "Message OPTIONS incoming..."; + MITK_INFO << mitk::RESTUtil::convertToUtf8(messageString); + + MitkResponse response(MitkRestStatusCodes::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"), mitk::RESTUtil::convertToTString(m_AllowOrigin)); + + message.reply(response); +} + +void SegmentationReworkREST::HandleGet(MitkRequest message) { auto messageString = message.to_string(); MITK_INFO << "Message GET incoming..."; MITK_INFO << mitk::RESTUtil::convertToUtf8(messageString); MITK_INFO << mitk::RESTUtil::convertToUtf8(message.request_uri().to_string()); auto uri = web::uri::decode(message.request_uri().to_string()); - if (uri.find(U("/robots.txt")) != std::string::npos || uri.find(U("/favicon.ico")) != std::string::npos || uri == U("/-") || uri.length() == 0) + if (uri.find(U("/robots.txt")) != std::string::npos || uri.find(U("/favicon.ico")) != std::string::npos || + uri == U("/-") || uri.length() == 0) { MITK_INFO << "ignore GET request: " << mitk::RESTUtil::convertToUtf8(messageString); return; } auto query = web::uri(uri).query(); auto httpParams = web::uri::split_query(query); // IHE Invoke Image Display style auto requestType = httpParams.find(U("requestType")); MITK_INFO << "parameters found: " << httpParams.size(); MitkResponse responsePositive(MitkRestStatusCodes::OK); responsePositive.set_body("call to mitk was successfully!"); if (requestType != httpParams.end() && requestType->second == U("IMAGE_SEG")) { try { auto studyUID = httpParams.at(U("studyUID")); auto imageSeriesUID = httpParams.at(U("imageSeriesUID")); auto segSeriesUID = httpParams.at(U("segSeriesUID")); DicomDTO dto; dto.imageSeriesUID = mitk::RESTUtil::convertToUtf8(imageSeriesUID); dto.studyUID = mitk::RESTUtil::convertToUtf8(studyUID); dto.segSeriesUIDA = mitk::RESTUtil::convertToUtf8(segSeriesUID); MITK_INFO << "studyUID: " << dto.studyUID; MITK_INFO << "imageSeriesUID: " << dto.imageSeriesUID; MITK_INFO << "segSeriesUID: " << dto.segSeriesUIDA; m_GetImageSegCallback(dto); MitkResponse response(MitkRestStatusCodes::OK); message.reply(responsePositive); } - catch (std::out_of_range& e) { + catch (std::out_of_range &e) + { message.reply(MitkRestStatusCodes::BadRequest, "oh man, that was not expected: " + std::string(e.what())); } - } else if (requestType != httpParams.end() && requestType->second == U("SEG_EVALUATION")) + } + else if (requestType != httpParams.end() && requestType->second == U("SEG_EVALUATION")) { // TODO: implement PUT handling as GET - } else if (requestType != httpParams.end() && requestType->second == U("IMAGE_SEG_LIST")) + } + else if (requestType != httpParams.end() && requestType->second == U("IMAGE_SEG_LIST")) { auto studyUID = httpParams.at(U("studyUID")); auto imageSeriesUID = httpParams.at(U("imageSeriesUID")); auto segSeriesUIDList = httpParams.at(U("segSeriesUIDList")); DicomDTO dto; dto.imageSeriesUID = mitk::RESTUtil::convertToUtf8(imageSeriesUID); dto.studyUID = mitk::RESTUtil::convertToUtf8(studyUID); auto segSeriesUIDListUtf8 = mitk::RESTUtil::convertToUtf8(segSeriesUIDList); - + std::istringstream f(segSeriesUIDListUtf8); std::string s; - while (getline(f, s, ',')) { + while (getline(f, s, ',')) + { dto.seriesUIDList.push_back(s); } MITK_INFO << "studyUID: " << dto.studyUID; MITK_INFO << "imageSeriesUID: " << dto.imageSeriesUID; MITK_INFO << "segSeriesUIDList: " << segSeriesUIDListUtf8; m_GetImageSegCallback(dto); message.reply(responsePositive); - } else if (requestType != httpParams.end() && requestType->second == U("ADD_SERIES")) + } + else if (requestType != httpParams.end() && requestType->second == U("ADD_SERIES")) { auto studyUID = httpParams.at(U("studyUID")); auto segSeriesUIDList = httpParams.at(U("seriesUIDList")); DicomDTO dto; dto.studyUID = mitk::RESTUtil::convertToUtf8(studyUID); auto seriesUIDListUtf8 = mitk::RESTUtil::convertToUtf8(segSeriesUIDList); std::istringstream f(seriesUIDListUtf8); std::string s; - while (getline(f, s, ',')) { + while (getline(f, s, ',')) + { dto.seriesUIDList.push_back(s); } MITK_INFO << "studyUID: " << dto.studyUID; MITK_INFO << "seriesUIDList: " << seriesUIDListUtf8; m_GetAddSeriesCallback(dto); message.reply(responsePositive); - } else + } + else { - message.reply(MitkRestStatusCodes::BadRequest, "unknown request type " + mitk::RESTUtil::convertToUtf8(requestType->second)); + message.reply(MitkRestStatusCodes::BadRequest, + "unknown request type " + mitk::RESTUtil::convertToUtf8(requestType->second)); } } void SegmentationReworkREST::HandlePut(MitkRequest message) { auto messageString = message.to_string(); MITK_INFO << "Message PUT incoming..."; MITK_INFO << mitk::RESTUtil::convertToUtf8(messageString); try { auto jsonMessage = message.extract_json().get(); auto messageTypeKey = jsonMessage.at(U("messageType")); if (messageTypeKey.as_string() == U("downloadData")) { auto imageStudyUIDKey = jsonMessage.at(U("studyUID")); auto srSeriesUIDKey = jsonMessage.at(U("srSeriesUID")); auto groundTruthKey = jsonMessage.at(U("groundTruth")); auto simScoreKey = jsonMessage.at(U("simScoreArray")); auto minSliceStartKey = jsonMessage.at(U("minSliceStart")); DicomDTO dto; dto.srSeriesUID = mitk::RESTUtil::convertToUtf8(srSeriesUIDKey.as_string()); dto.groundTruth = mitk::RESTUtil::convertToUtf8(groundTruthKey.as_string()); dto.studyUID = mitk::RESTUtil::convertToUtf8(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; m_PutCallback(dto); emit InvokeUpdateChartWidget(); } else { message.reply(MitkRestStatusCodes::BadRequest, "Oh man, i can only deal with 'messageType' = 'downloadData'..."); } } catch (MitkJsonException &e) { MITK_ERROR << e.what() << ".. oh man, that was not expected"; message.reply(MitkRestStatusCodes::BadRequest, "oh man, that was not expected"); return; } MitkResponse response(MitkRestStatusCodes::OK); - response.headers().add(U("Access-Control-Allow-Origin"), U("localhost:9000/*")); + response.headers().add(U("Access-Control-Allow-Origin"), mitk::RESTUtil::convertToTString(m_AllowOrigin)); response.set_body("Sure, i got you.. have an awesome day"); message.reply(response); return; } \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.h b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.h index d867937c6c..85b819ef6f 100644 --- a/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.h +++ b/Plugins/org.mitk.gui.qt.segmentation.rework/src/internal/SegmentationReworkREST.h @@ -1,79 +1,75 @@ /*=================================================================== 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 SegmentationReworkREST_h #define SegmentationReworkREST_h #include class SegmentationReworkREST : public mitk::RESTServer { Q_OBJECT public: struct DicomDTO { std::string segSeriesUIDA; std::string segSeriesUIDB; std::string imageSeriesUID; std::string studyUID; std::string segInstanceUIDA; std::string segInstanceUIDB; std::string srSeriesUID; std::vector seriesUIDList; std::vector simScoreArray; int minSliceStart; std::string groundTruth; }; SegmentationReworkREST(); SegmentationReworkREST(utility::string_t url); ~SegmentationReworkREST(); void HandlePut(MitkRequest message); void HandleGet(MitkRequest message); + void HandleOptions(MitkRequest message); - void SetPutCallback(std::function callback) - { - m_PutCallback = callback; - } + void SetPutCallback(std::function callback) { m_PutCallback = callback; } - void SetGetImageSegCallback(std::function callback) - { - m_GetImageSegCallback = callback; - } + void SetGetImageSegCallback(std::function callback) { m_GetImageSegCallback = callback; } - void SetGetEvalCallback(std::function callback) - { - m_GetEvalCallback = callback; - } + void SetGetEvalCallback(std::function callback) { m_GetEvalCallback = callback; } - void SetGetAddSeriesCallback(std::function callback) - { - m_GetAddSeriesCallback = callback; + void SetGetAddSeriesCallback(std::function callback) { m_GetAddSeriesCallback = callback; } + + void SetAllowOrigin(std::string origin) + { + m_AllowOrigin = origin; } signals: void InvokeUpdateChartWidget(); private: std::function m_PutCallback; std::function m_GetImageSegCallback; std::function m_GetEvalCallback; std::function m_GetAddSeriesCallback; + + std::string m_AllowOrigin; }; #endif // SegmentationReworkREST_h 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 37c485b397..7b11d731e6 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,699 +1,704 @@ /*=================================================================== 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"); // 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::OnRestartConnection); connect(m_Controls.testConnection, &QPushButton::clicked, this, &SegmentationReworkView::TestConnection); 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 restURL = U("http://localhost:8000"); - RestartConnection("http://e230-pc03.inet.dkfz-heidelberg.de:8090"); + //m_HttpHandler->SetAllowOrigin("https://10.128.129.136"); + // RestartConnection("http://e230-pc03.inet.dkfz-heidelberg.de:8090"); + m_HttpHandler->SetAllowOrigin("https://10.128.129.136"); + + RestartConnection("http://10.128.129.136:8080"); 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); } } pplx::task SegmentationReworkView::TestConnection() { typedef std::map ParamMap; ParamMap seriesInstancesParams; seriesInstancesParams.insert((ParamMap::value_type({"limit"}, {"1"}))); m_Controls.connectionStatus->setText(QString("Testing connection ...")); return m_DICOMWeb->QidoRSInstances(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 SegmentationReworkView::OnRestartConnection() +void SegmentationReworkView::OnRestartConnection() { RestartConnection(); } void SegmentationReworkView::RestartConnection(std::string newHost) { auto hostBefore = m_Controls.dcm4cheeURL->text(); std::string host; if (newHost.empty()) { host = m_Controls.dcm4cheeHostValue->text().toStdString(); } else { host = newHost; } std::string url = host + "/dcm4chee-arc/aets/DCM4CHEE"; if (!host.empty()) { MITK_INFO << "Restarting connection to " << url << " ..."; m_Controls.connectionStatus->setText(QString("Restarting connection...")); - m_Controls.dcm4cheeURL->setText({(utility::conversions::to_utf8string(url).c_str())}); + m_Controls.dcm4cheeURL->setText({(utility::conversions::to_utf8string(url).c_str())}); try { m_DICOMWeb = new mitk::DICOMWeb(utility::conversions::to_string_t(url)); } catch (std::exception &e) { MITK_WARN << e.what(); - m_Controls.dcm4cheeURL->setText(hostBefore); + m_Controls.dcm4cheeURL->setText(hostBefore); m_Controls.connectionStatus->setText(QString("Invalid host!")); return; } - + if (!TestConnection().get()) { MITK_INFO << "Restart did not work.."; m_Controls.connectionStatus->setText(QString("No PACS server available under given host!")); } - else{ + else + { MITK_INFO << "requests to pacs are sent to: " << url; } } else { m_Controls.connectionStatus->setText(QString("Host must not be empty!")); } } 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->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"}); + emit InvokeProgress(80, {"persist reworked SEG to evaluation database"}); MitkUriBuilder queryBuilder(U("tasks/evaluations/")); queryBuilder.append_query(U("srUID"), utility::conversions::to_string_t(m_SRUID)); - 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"}); - }); - }); + //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); }