changeset 5790:a3d283f61304 find-refactoring

improved handling of DicomSequences in parent
author Alain Mazy <am@orthanc.team>
date Wed, 18 Sep 2024 09:34:52 +0200
parents 40ad08b75d84
children 89a13d8ec80b
files OrthancFramework/Sources/DicomFormat/DicomMap.cpp OrthancFramework/Sources/DicomFormat/DicomMap.h OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp OrthancServer/Sources/ResourceFinder.cpp
diffstat 4 files changed, 93 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomFormat/DicomMap.cpp	Tue Sep 17 17:16:42 2024 +0200
+++ b/OrthancFramework/Sources/DicomFormat/DicomMap.cpp	Wed Sep 18 09:34:52 2024 +0200
@@ -739,21 +739,6 @@
     }
   }
 
-  void DicomMap::RemoveComputedTags(std::set<DicomTag>& tags)
-  {
-    std::set<DicomTag> tagsToRemove;
-
-    for (std::set<DicomTag>::const_iterator it = tags.begin(); it != tags.end(); ++it)
-    {
-      if (IsComputedTag(*it))
-      {
-        tagsToRemove.insert(*it);
-      }
-    }
-
-    Toolbox::RemoveSets(tags, tagsToRemove);
-  }
-
   bool DicomMap::HasOnlyComputedTags(const std::set<DicomTag>& tags)
   {
     if (tags.size() == 0)
--- a/OrthancFramework/Sources/DicomFormat/DicomMap.h	Tue Sep 17 17:16:42 2024 +0200
+++ b/OrthancFramework/Sources/DicomFormat/DicomMap.h	Wed Sep 18 09:34:52 2024 +0200
@@ -142,8 +142,6 @@
 
     static bool HasOnlyComputedTags(const std::set<DicomTag>& tags);
 
-    static void RemoveComputedTags(std::set<DicomTag>& tags);
-
     static bool HasComputedTags(const std::set<DicomTag>& tags, ResourceType level);
 
     static bool HasComputedTags(const std::set<DicomTag>& tags);
--- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp	Tue Sep 17 17:16:42 2024 +0200
+++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp	Wed Sep 18 09:34:52 2024 +0200
@@ -469,42 +469,86 @@
         }
       }
 
-      // need MainDicomTags from parent ?
-      if (requestLevel > ResourceType_Patient && request.GetParentSpecification(static_cast<ResourceType>(requestLevel - 1)).IsRetrieveMainDicomTags())
+      
+      if (requestLevel > ResourceType_Patient)
       {
-        sql = "SELECT currentLevel.internalId, tagGroup, tagElement, value "
-              "FROM MainDicomTags "
-              "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId "
-              "INNER JOIN Lookup ON MainDicomTags.id = currentLevel.parentId";
+        // need MainDicomTags from parent ?
+        if (request.GetParentSpecification(static_cast<ResourceType>(requestLevel - 1)).IsRetrieveMainDicomTags())
+        {
+          sql = "SELECT currentLevel.internalId, tagGroup, tagElement, value "
+                "FROM MainDicomTags "
+                "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId "
+                "INNER JOIN Lookup ON MainDicomTags.id = currentLevel.parentId";
 
-        SQLite::Statement s(db_, SQLITE_FROM_HERE, sql);
-        while (s.Step())
+          SQLite::Statement s(db_, SQLITE_FROM_HERE, sql);
+          while (s.Step())
+          {
+            FindResponse::Resource& res = response.GetResourceByInternalId(s.ColumnInt64(0));
+            res.AddStringDicomTag(static_cast<ResourceType>(requestLevel - 1), 
+                                  static_cast<uint16_t>(s.ColumnInt(1)),
+                                  static_cast<uint16_t>(s.ColumnInt(2)),
+                                  s.ColumnString(3));
+          }
+        }
+
+        // need metadata from parent ?
+        if (request.GetParentSpecification(static_cast<ResourceType>(requestLevel - 1)).IsRetrieveMetadata())
         {
-          FindResponse::Resource& res = response.GetResourceByInternalId(s.ColumnInt64(0));
-          res.AddStringDicomTag(static_cast<ResourceType>(requestLevel - 1), 
-                                static_cast<uint16_t>(s.ColumnInt(1)),
-                                static_cast<uint16_t>(s.ColumnInt(2)),
-                                s.ColumnString(3));
+          sql = "SELECT currentLevel.internalId, type, value "
+                "FROM Metadata "
+                "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId "
+                "INNER JOIN Lookup ON Metadata.id = currentLevel.parentId";
+
+          SQLite::Statement s(db_, SQLITE_FROM_HERE, sql);
+          while (s.Step())
+          {
+            FindResponse::Resource& res = response.GetResourceByInternalId(s.ColumnInt64(0));
+            res.AddMetadata(static_cast<ResourceType>(requestLevel - 1), 
+                            static_cast<MetadataType>(s.ColumnInt(1)),
+                            s.ColumnString(2));
+          }
         }
       }
 
-      // need MainDicomTags from grandparent ?
-      if (requestLevel > ResourceType_Study && request.GetParentSpecification(static_cast<ResourceType>(requestLevel - 2)).IsRetrieveMainDicomTags())
+      if (requestLevel > ResourceType_Study)
       {
-        sql = "SELECT currentLevel.internalId, tagGroup, tagElement, value "
-              "FROM MainDicomTags "
-              "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId "
-              "INNER JOIN Resources parentLevel ON currentLevel.parentId = parentLevel.internalId "
-              "INNER JOIN Lookup ON MainDicomTags.id = parentLevel.parentId";
+        // need MainDicomTags from grandparent ?
+        if (request.GetParentSpecification(static_cast<ResourceType>(requestLevel - 2)).IsRetrieveMainDicomTags())
+        {
+          sql = "SELECT currentLevel.internalId, tagGroup, tagElement, value "
+                "FROM MainDicomTags "
+                "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId "
+                "INNER JOIN Resources parentLevel ON currentLevel.parentId = parentLevel.internalId "
+                "INNER JOIN Lookup ON MainDicomTags.id = parentLevel.parentId";
 
-        SQLite::Statement s(db_, SQLITE_FROM_HERE, sql);
-        while (s.Step())
+          SQLite::Statement s(db_, SQLITE_FROM_HERE, sql);
+          while (s.Step())
+          {
+            FindResponse::Resource& res = response.GetResourceByInternalId(s.ColumnInt64(0));
+            res.AddStringDicomTag(static_cast<ResourceType>(requestLevel - 2), 
+                                  static_cast<uint16_t>(s.ColumnInt(1)),
+                                  static_cast<uint16_t>(s.ColumnInt(2)),
+                                  s.ColumnString(3));
+          }
+        }
+
+        // need metadata from grandparent ?
+        if (request.GetParentSpecification(static_cast<ResourceType>(requestLevel - 2)).IsRetrieveMetadata())
         {
-          FindResponse::Resource& res = response.GetResourceByInternalId(s.ColumnInt64(0));
-          res.AddStringDicomTag(static_cast<ResourceType>(requestLevel - 2), 
-                                static_cast<uint16_t>(s.ColumnInt(1)),
-                                static_cast<uint16_t>(s.ColumnInt(2)),
-                                s.ColumnString(3));
+          sql = "SELECT currentLevel.internalId, type, value "
+                "FROM Metadata "
+                "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId "
+                "INNER JOIN Resources parentLevel ON currentLevel.parentId = parentLevel.internalId "
+                "INNER JOIN Lookup ON Metadata.id = parentLevel.parentId";
+
+          SQLite::Statement s(db_, SQLITE_FROM_HERE, sql);
+          while (s.Step())
+          {
+            FindResponse::Resource& res = response.GetResourceByInternalId(s.ColumnInt64(0));
+            res.AddMetadata(static_cast<ResourceType>(requestLevel - 2), 
+                            static_cast<MetadataType>(s.ColumnInt(1)),
+                            s.ColumnString(2));
+          }
         }
       }
 
--- a/OrthancServer/Sources/ResourceFinder.cpp	Tue Sep 17 17:16:42 2024 +0200
+++ b/OrthancServer/Sources/ResourceFinder.cpp	Wed Sep 18 09:34:52 2024 +0200
@@ -190,7 +190,7 @@
   {
     // read all main sequences from DB
     std::string serializedSequences;
-    if (resource.LookupMetadata(serializedSequences, resource.GetLevel(), MetadataType_MainDicomSequences))
+    if (resource.LookupMetadata(serializedSequences, level, MetadataType_MainDicomSequences))
     {
       Json::Value jsonMetadata;
       Toolbox::ReadJson(jsonMetadata, serializedSequences);
@@ -651,6 +651,7 @@
         else
         {
           request_.GetParentSpecification(ResourceType_Study).SetRetrieveMainDicomTags(true);
+          request_.GetParentSpecification(ResourceType_Study).SetRetrieveMetadata(true);  // to get the MainDicomSequences
         }
       }
     }
@@ -674,6 +675,7 @@
         else
         {
           request_.GetParentSpecification(ResourceType_Study).SetRetrieveMainDicomTags(true);
+          request_.GetParentSpecification(ResourceType_Study).SetRetrieveMetadata(true);  // to get the MainDicomSequences
         }
       }
     }
@@ -698,6 +700,7 @@
         else
         {
           request_.GetParentSpecification(ResourceType_Series).SetRetrieveMainDicomTags(true);
+          request_.GetParentSpecification(ResourceType_Series).SetRetrieveMetadata(true);  // to get the MainDicomSequences
         }
       }
     }
@@ -794,23 +797,29 @@
                                   ResourceType level/*,
                                   const std::set<DicomTag>& tags*/)
   {
-    if (!remainingRequestedTags.empty())
+    if (!remainingRequestedTags.empty() && level <= resource.GetLevel())
     {
-      DicomMap m;
-      resource.GetAllMainDicomTags(m);                          // DicomTags from DB
-      GetMainDicomSequencesFromMetadata(m, resource, resource.GetLevel());    // DicomSequences from metadata
-      
-      // check which tags have been saved in DB; that's the way to know if they are missing because they were not saved or because they have no value
       std::set<DicomTag> savedMainDicomTags;
-      std::string signature = DicomMap::GetDefaultMainDicomTagsSignature(ResourceType_Study); // default signature in case it's not in the metadata (= the signature for 1.11.0)
-      if (resource.LookupMetadata(signature, resource.GetLevel(), MetadataType_MainDicomTagsSignature))
+
+      DicomMap m;
+      resource.GetMainDicomTags(m, level);                          // read DicomTags from DB
+
+      if (resource.GetMetadata(level).size() > 0)
       {
-        if (level == ResourceType_Study) // when we retrieve the study tags, we actually also get the patient tags that are also saved at study level but not included in the signature
+        GetMainDicomSequencesFromMetadata(m, resource, level);        // read DicomSequences from metadata
+      
+        // check which tags have been saved in DB; that's the way to know if they are missing because they were not saved or because they have no value
+        
+        std::string signature = DicomMap::GetDefaultMainDicomTagsSignature(ResourceType_Study); // default signature in case it's not in the metadata (= the signature for 1.11.0)
+        if (resource.LookupMetadata(signature, level, MetadataType_MainDicomTagsSignature))
         {
-          signature += ";" + DicomMap::GetDefaultMainDicomTagsSignature(ResourceType_Patient); // append the default signature (from before 1.11.0)
+          if (level == ResourceType_Study) // when we retrieve the study tags, we actually also get the patient tags that are also saved at study level but not included in the signature
+          {
+            signature += ";" + DicomMap::GetDefaultMainDicomTagsSignature(ResourceType_Patient); // append the default signature (from before 1.11.0)
+          }
+
+          FromDcmtkBridge::ParseListOfTags(savedMainDicomTags, signature);
         }
-
-        FromDcmtkBridge::ParseListOfTags(savedMainDicomTags, signature);
       }
 
       std::set<DicomTag> copiedTags;