changeset 567:de4a56ecd2bc am-experimental

wip: reduce the number of calls
author Alain Mazy <am@osimis.io>
date Wed, 14 Jun 2023 14:47:13 +0200
parents 29c43ae730a8
children 2c494f872f70
files Plugin/WadoRs.cpp TODO
diffstat 2 files changed, 53 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/Plugin/WadoRs.cpp	Thu May 25 17:38:22 2023 +0200
+++ b/Plugin/WadoRs.cpp	Wed Jun 14 14:47:13 2023 +0200
@@ -875,6 +875,7 @@
                                   OrthancPlugins::MetadataMode mode,
                                   MainDicomTagsCache& cache,
                                   const std::string& orthancId,
+                                  Orthanc::DicomMap* dicom,
                                   const std::string& studyInstanceUid,
                                   const std::string& seriesInstanceUid,
                                   const std::string& wadoBase)
@@ -884,28 +885,31 @@
          !seriesInstanceUid.empty() &&
          !wadoBase.empty());
 
-  Orthanc::DicomMap dicom;
-
-  if (!cache.GetInstance(dicom, mode, orthancId))
-  {
-    throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource, "instance not found: " + orthancId);
-  }
-
   switch (mode)
   {
     case OrthancPlugins::MetadataMode_MainDicomTags:
     case OrthancPlugins::MetadataMode_Extrapolate:
     {
-      writer.AddOrthancMap(dicom);
-      break;
+      // TODO: reactivate
+      // Orthanc::DicomMap dicom;
+
+      // if (!cache.GetInstance(dicom, mode, orthancId))
+      // {
+      //   throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource, "instance not found: " + orthancId);
+      // }
+
+      // writer.AddOrthancMap(dicom);
+      // break;
     }
 
     case OrthancPlugins::MetadataMode_Full:
     {
+      assert(dicom != NULL);
+
       const std::string bulkRoot = (wadoBase +
                                     "studies/" + studyInstanceUid +
                                     "/series/" + seriesInstanceUid + 
-                                    "/instances/" + dicom.GetStringValue(Orthanc::DICOM_TAG_SOP_INSTANCE_UID, "", false) + "/bulk");
+                                    "/instances/" + dicom->GetStringValue(Orthanc::DICOM_TAG_SOP_INSTANCE_UID, "", false) + "/bulk");
 
       // On a SSD drive, this version is twice slower than if using
       // cache (see below)
@@ -1145,16 +1149,16 @@
 
 
 
-
+typedef std::map<std::string, boost::shared_ptr<Orthanc::DicomMap> >  DicomMaps;
 
-static void GetChildrenIdentifiers(std::list<std::string>& target,
+static void GetChildrenIdentifiers(DicomMaps& childrenDicomMaps,
                                    std::string& resourceDicomUid,
                                    Orthanc::ResourceType level,
                                    const std::string& orthancId)
 {
-  target.clear();
+  childrenDicomMaps.clear();
 
-  const char* childrenTag = NULL;
+  const char* childrenRoute = NULL;
   const char* dicomUidTag = NULL;
   std::string uri;
 
@@ -1162,13 +1166,13 @@
   {
     case Orthanc::ResourceType_Study:
       uri = "/studies/" + orthancId;
-      childrenTag = "Series";
+      childrenRoute = "series";
       dicomUidTag = "StudyInstanceUID";
       break;
        
     case Orthanc::ResourceType_Series:
       uri = "/series/" + orthancId;
-      childrenTag = "Instances";
+      childrenRoute = "instances";
       dicomUidTag = "SeriesInstanceUID";
       break;
 
@@ -1176,24 +1180,34 @@
       throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
   }
 
-  assert(childrenTag != NULL && dicomUidTag != NULL);
+  assert(childrenRoute != NULL && dicomUidTag != NULL);
   
+  // get the resource itself
   Json::Value resource;
   if (OrthancPlugins::RestApiGet(resource, uri, false))
   {
-    if (resource.type() != Json::objectValue || !resource.isMember(childrenTag) 
+    if (resource.type() != Json::objectValue 
       || !resource.isMember(MAIN_DICOM_TAGS) || !resource[MAIN_DICOM_TAGS].isMember(dicomUidTag))
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
     }
 
-    const Json::Value& children = resource[childrenTag];
     resourceDicomUid = resource[MAIN_DICOM_TAGS][dicomUidTag].asString();
 
-    for (Json::Value::ArrayIndex i = 0; i < children.size(); i++)
+    // get the children resources
+    Json::Value childResources;
+    if (OrthancPlugins::RestApiGet(childResources, uri + "/" + childrenRoute + "?expand&full", false))
     {
-      target.push_back(children[i].asString());
+      for (Json::Value::ArrayIndex i = 0; i < childResources.size(); i++)
+      {
+        const Json::Value& child = childResources[i];
+        Orthanc::DicomMap dicom;
+        dicom.FromDicomAsJson(child[MAIN_DICOM_TAGS], false /* append */, true /* parseSequences */);
+        childrenDicomMaps[child["ID"].asString()] = boost::shared_ptr<Orthanc::DicomMap>(dicom.Clone());
+      }
+
     }
+
   }  
 }
 
@@ -1220,19 +1234,20 @@
     {
       OrthancPlugins::DicomWebFormatter::HttpWriter writer(output, isXml);
 
-      std::list<std::string> series;
+      DicomMaps seriesDicomMaps;
       std::string studyDicomUid;
-      GetChildrenIdentifiers(series, studyDicomUid, Orthanc::ResourceType_Study, studyOrthancId);
+      GetChildrenIdentifiers(seriesDicomMaps, studyDicomUid, Orthanc::ResourceType_Study, studyOrthancId);
 
-      for (std::list<std::string>::const_iterator s = series.begin(); s != series.end(); ++s)
+      for (DicomMaps::const_iterator s = seriesDicomMaps.begin(); s != seriesDicomMaps.end(); ++s)
       {
-        std::list<std::string> instances;
+        DicomMaps instancesDicomMaps;
         std::string seriesDicomUid;
-        GetChildrenIdentifiers(instances, seriesDicomUid, Orthanc::ResourceType_Series, *s);
+        GetChildrenIdentifiers(instancesDicomMaps, seriesDicomUid, Orthanc::ResourceType_Series, s->first);
 
-        for (std::list<std::string>::const_iterator i = instances.begin(); i != instances.end(); ++i)
+        // TODO: parallelize (share code with RetrieveSeriesMetadata)
+        for (DicomMaps::const_iterator i = instancesDicomMaps.begin(); i != instancesDicomMaps.end(); ++i)
         {
-          WriteInstanceMetadata(writer, mode, cache, *i, studyInstanceUid, seriesDicomUid,
+          WriteInstanceMetadata(writer, mode, cache, i->first, i->second.get(), studyInstanceUid, seriesDicomUid,
                                 OrthancPlugins::Configuration::GetBasePublicUrl(request));
         }
       }
@@ -1278,13 +1293,14 @@
       }
       else
       {
-        std::list<std::string> instances;
-        std::string seriesDicomUid;  // not used
-        GetChildrenIdentifiers(instances, seriesDicomUid, Orthanc::ResourceType_Series, seriesOrthancId);
+        DicomMaps instancesDicomMaps;
+        std::string seriesDicomUid;
+        GetChildrenIdentifiers(instancesDicomMaps, seriesDicomUid, Orthanc::ResourceType_Series, seriesOrthancId);
 
-        for (std::list<std::string>::const_iterator i = instances.begin(); i != instances.end(); ++i)
+        // TODO: parallelize
+        for (DicomMaps::const_iterator i = instancesDicomMaps.begin(); i != instancesDicomMaps.end(); ++i)
         {
-          WriteInstanceMetadata(writer, mode, cache, *i, studyInstanceUid, seriesInstanceUid,
+          WriteInstanceMetadata(writer, mode, cache, i->first, i->second.get(), studyInstanceUid, seriesDicomUid,
                                 OrthancPlugins::Configuration::GetBasePublicUrl(request));
         }
       }
@@ -1312,7 +1328,7 @@
     if (LocateInstance(output, orthancId, studyInstanceUid, seriesInstanceUid, sopInstanceUid, request))
     {
       OrthancPlugins::DicomWebFormatter::HttpWriter writer(output, isXml);
-      WriteInstanceMetadata(writer, OrthancPlugins::MetadataMode_Full, cache, orthancId, studyInstanceUid,
+      WriteInstanceMetadata(writer, OrthancPlugins::MetadataMode_Full, cache, orthancId, NULL, studyInstanceUid,
                             seriesInstanceUid, OrthancPlugins::Configuration::GetBasePublicUrl(request));
       writer.Send();      
     }
--- a/TODO	Thu May 25 17:38:22 2023 +0200
+++ b/TODO	Wed Jun 14 14:47:13 2023 +0200
@@ -33,6 +33,9 @@
     
     There is still a high cost for serialization (which is now simply copying and merging json nodes)
 
+    // The "Full" mode optimized with reading only "file-until-pixel-data" and with a single call to get all instances tags is now
+    -> 0.750 s
+
 
   - note that all measurements have been performed on a DB with a single series !  We should repeat 
     that with a more realistic DB
\ No newline at end of file