Mercurial > hg > orthanc-dicomweb
changeset 525:a4c93eea9403
Refactored the way WADO-RS locate resources
author | Alain Mazy <am@osimis.io> |
---|---|
date | Wed, 29 Jun 2022 10:22:25 +0200 |
parents | 43d4ba62a9ba |
children | 389445feb3a0 |
files | NEWS Plugin/WadoRs.cpp TODO |
diffstat | 3 files changed, 84 insertions(+), 120 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Tue Jun 28 18:37:28 2022 +0200 +++ b/NEWS Wed Jun 29 10:22:25 2022 +0200 @@ -4,6 +4,8 @@ * if using "MainDicomTags" mode for "SeriesMetadata" and "StudiesMetadata", the plugin now returns the "ExtraMainDicomTags" that have been configured on Orthanc side. * Now able to return sequences stored in "ExtraMainDicomTags" (with Orthanc 1.11.1) +* refactored the way WADO-RS locate resources. If the same SeriesInstanceUID is re-used + across multiple Studies, the plugin should now locate it correctly. Version 1.8 (2022-05-09) ========================
--- a/Plugin/WadoRs.cpp Tue Jun 28 18:37:28 2022 +0200 +++ b/Plugin/WadoRs.cpp Wed Jun 29 10:22:25 2022 +0200 @@ -801,12 +801,13 @@ #endif } - - -bool LocateStudy(OrthancPluginRestOutput* output, - std::string& orthancId, - std::string& studyInstanceUid, - const OrthancPluginHttpRequest* request) +bool LocateResource(OrthancPluginRestOutput* output, + std::string& orthancId, + std::string& studyInstanceUid, + std::string& seriesInstanceUid, + std::string& sopInstanceUid, + const std::string& level, + const OrthancPluginHttpRequest* request) { OrthancPluginContext* context = OrthancPlugins::GetGlobalContext(); @@ -816,25 +817,68 @@ return false; } + { + std::string body; + Json::Value payload; + Json::Value payloadQuery; + + payload["Level"] = level; + + if (!sopInstanceUid.empty()) + { + payloadQuery["SOPInstanceUID"] = sopInstanceUid; + } + + if (!seriesInstanceUid.empty()) + { + payloadQuery["SeriesInstanceUID"] = seriesInstanceUid; + } + + payloadQuery["StudyInstanceUID"] = studyInstanceUid; + payload["Query"] = payloadQuery; + + OrthancPlugins::WriteFastJson(body, payload); + + Json::Value resources; + if (!OrthancPlugins::RestApiPost(resources, "/tools/find", body, false) || + resources.type() != Json::arrayValue) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + if (resources.size() == 0) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem, + "Accessing an inexistent " + level + " with WADO-RS: " + studyInstanceUid + "/" + seriesInstanceUid + "/" + sopInstanceUid); + } + if (resources.size() > 1) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem, + "Multiple " + level + " found for WADO-RS: " + studyInstanceUid + "/" + seriesInstanceUid + "/" + sopInstanceUid); + } + orthancId = resources[0].asString(); + return true; + } +} + + + +bool LocateStudy(OrthancPluginRestOutput* output, + std::string& orthancId, + std::string& studyInstanceUid, + const OrthancPluginHttpRequest* request) +{ + std::string sopInstanceUid; + std::string seriesInstanceUid; studyInstanceUid = request->groups[0]; - try - { - OrthancPlugins::OrthancString tmp; - tmp.Assign(OrthancPluginLookupStudy(context, studyInstanceUid.c_str())); - - if (tmp.GetContent() != NULL) - { - tmp.ToString(orthancId); - return true; - } - } - catch (Orthanc::OrthancException&) - { - } - - throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem, - "Accessing an inexistent study with WADO-RS: " + studyInstanceUid); + return LocateResource(output, + orthancId, + studyInstanceUid, + seriesInstanceUid, + sopInstanceUid, + "Study", + request); } @@ -844,55 +888,17 @@ std::string& seriesInstanceUid, const OrthancPluginHttpRequest* request) { - OrthancPluginContext* context = OrthancPlugins::GetGlobalContext(); - - if (request->method != OrthancPluginHttpMethod_Get) - { - OrthancPluginSendMethodNotAllowed(context, output, "GET"); - return false; - } - + std::string sopInstanceUid; studyInstanceUid = request->groups[0]; seriesInstanceUid = request->groups[1]; - bool found = false; - - try - { - OrthancPlugins::OrthancString tmp; - tmp.Assign(OrthancPluginLookupSeries(context, seriesInstanceUid.c_str())); - - if (tmp.GetContent() != NULL) - { - tmp.ToString(orthancId); - found = true; - } - } - catch (Orthanc::OrthancException&) - { - } - - if (!found) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem, - "Accessing an inexistent series with WADO-RS: " + seriesInstanceUid); - } - - Json::Value study; - if (!OrthancPlugins::RestApiGet(study, "/series/" + orthancId + "/study", false)) - { - OrthancPluginSendHttpStatusCode(context, output, 404); - return false; - } - else if (study[MAIN_DICOM_TAGS]["StudyInstanceUID"].asString() != studyInstanceUid) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem, - "No series " + seriesInstanceUid + " in study " + studyInstanceUid); - } - else - { - return true; - } + return LocateResource(output, + orthancId, + studyInstanceUid, + seriesInstanceUid, + sopInstanceUid, + "Series", + request); } @@ -903,50 +909,17 @@ std::string& sopInstanceUid, const OrthancPluginHttpRequest* request) { - OrthancPluginContext* context = OrthancPlugins::GetGlobalContext(); - - if (request->method != OrthancPluginHttpMethod_Get) - { - OrthancPluginSendMethodNotAllowed(context, output, "GET"); - return false; - } - studyInstanceUid = request->groups[0]; seriesInstanceUid = request->groups[1]; sopInstanceUid = request->groups[2]; - - { - OrthancPlugins::OrthancString tmp; - tmp.Assign(OrthancPluginLookupInstance(context, sopInstanceUid.c_str())); - if (tmp.GetContent() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem, - "Accessing an inexistent instance with WADO-RS: " + sopInstanceUid); - } - - tmp.ToString(orthancId); - } - - Json::Value study, series; - if (!OrthancPlugins::RestApiGet(series, "/instances/" + orthancId + "/series", false) || - !OrthancPlugins::RestApiGet(study, "/instances/" + orthancId + "/study", false)) - { - OrthancPluginSendHttpStatusCode(context, output, 404); - return false; - } - else if (study[MAIN_DICOM_TAGS]["StudyInstanceUID"].asString() != studyInstanceUid || - series[MAIN_DICOM_TAGS]["SeriesInstanceUID"].asString() != seriesInstanceUid) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem, - "Instance " + sopInstanceUid + - " is not both in study " + studyInstanceUid + - " and in series " + seriesInstanceUid); - } - else - { - return true; - } + return LocateResource(output, + orthancId, + studyInstanceUid, + seriesInstanceUid, + sopInstanceUid, + "Instance", + request); }
--- a/TODO Tue Jun 28 18:37:28 2022 +0200 +++ b/TODO Wed Jun 29 10:22:25 2022 +0200 @@ -1,17 +1,6 @@ * Implement capabilities: https://www.dicomstandard.org/using/dicomweb/capabilities/ from https://groups.google.com/d/msgid/orthanc-users/c60227f2-c6da-4fd9-9b03-3ce9bf7d1af5n%40googlegroups.com?utm_medium=email&utm_source=footer -* use the same DicomMap as the core of Orthanc (wrt ExtraMainDicomTags) - from https://groups.google.com/g/orthanc-users/c/-ZKW9967DW4/m/9T3bwHeCAAAJ - command to test: - curl -H "Accept: application/json" http://localhost:8044/dicom-web/studies/1.2.840.113619.2.404.3.2831156996.875.1599094730.441/series/1.2.840.113619.2.404.3.2831156996.875.1599094730.453.5/metadata - -> return MainDicomSequences - - -* handle same SeriesInstanceUID in different studies: - from https://groups.google.com/g/orthanc-users/c/nSBcMP_ri4o/m/sQxqKa72BAAJ - We can indeed solve the issue by calling tools/find instead of tools/lookup in the LocateSeries method - * From Sylvain: curl http://localhost:8044/dicom-web/instances?StudyInstanceUID=1.2.3.4 shall return not only the instance tags but also the study level tags. See section 10.6.3.3.3 "Instance Resources" in https://dicom.nema.org/medical/dicom/current/output/html/part18.html: