changeset 3006:0e1755e5efd0

DicomMap::ExtractMainDicomTags()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 13 Dec 2018 12:37:10 +0100
parents 8265a6b56100
children 45a4a1571b4e 9f859a18cbc2
files Core/DicomFormat/DicomMap.cpp Core/DicomFormat/DicomMap.h LinuxCompilation.txt OrthancServer/ServerIndex.cpp OrthancServer/ServerIndex.h UnitTestsSources/DicomMapTests.cpp
diffstat 6 files changed, 175 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/Core/DicomFormat/DicomMap.cpp	Wed Dec 12 15:42:33 2018 +0100
+++ b/Core/DicomFormat/DicomMap.cpp	Thu Dec 13 12:37:10 2018 +0100
@@ -1021,6 +1021,54 @@
   }
 
 
+  void DicomMap::Merge(const DicomMap& other)
+  {
+    for (Map::const_iterator it = other.map_.begin();
+         it != other.map_.end(); ++it)
+    {
+      assert(it->second != NULL);
+
+      if (map_.find(it->first) == map_.end())
+      {
+        map_[it->first] = it->second->Clone();
+      }
+    }
+  }
+
+
+  void DicomMap::ExtractMainDicomTagsInternal(const DicomMap& other,
+                                              ResourceType level)
+  {
+    const DicomTag* tags = NULL;
+    size_t size = 0;
+
+    LoadMainDicomTags(tags, size, level);
+    assert(tags != NULL && size > 0);
+
+    for (size_t i = 0; i < size; i++)
+    {
+      Map::const_iterator found = other.map_.find(tags[i]);
+
+      if (found != other.map_.end() &&
+          map_.find(tags[i]) == map_.end())
+      {
+        assert(found->second != NULL);
+        map_[tags[i]] = found->second->Clone();
+      }
+    }
+  }
+    
+
+  void DicomMap::ExtractMainDicomTags(const DicomMap& other)
+  {
+    Clear();
+    ExtractMainDicomTagsInternal(other, ResourceType_Patient);
+    ExtractMainDicomTagsInternal(other, ResourceType_Study);
+    ExtractMainDicomTagsInternal(other, ResourceType_Series);
+    ExtractMainDicomTagsInternal(other, ResourceType_Instance);
+  }    
+
+
   void DicomMap::Serialize(Json::Value& target) const
   {
     target = Json::objectValue;
--- a/Core/DicomFormat/DicomMap.h	Wed Dec 12 15:42:33 2018 +0100
+++ b/Core/DicomFormat/DicomMap.h	Thu Dec 13 12:37:10 2018 +0100
@@ -59,7 +59,7 @@
                   uint16_t element, 
                   DicomValue* value);
 
-    void SetValue(DicomTag tag, 
+    void SetValue(DicomTag tag,
                   DicomValue* value);
 
     void ExtractTags(DicomMap& source,
@@ -68,6 +68,9 @@
    
     static void GetMainDicomTagsInternal(std::set<DicomTag>& result, ResourceType level);
 
+    void ExtractMainDicomTagsInternal(const DicomMap& other,
+                                      ResourceType level);
+
   public:
     DicomMap()
     {
@@ -218,6 +221,10 @@
                      const DicomTag& tag) const;
 
     void FromDicomAsJson(const Json::Value& dicomAsJson);
+
+    void Merge(const DicomMap& other);
+
+    void ExtractMainDicomTags(const DicomMap& other); 
     
     void Serialize(Json::Value& target) const;
 
--- a/LinuxCompilation.txt	Wed Dec 12 15:42:33 2018 +0100
+++ b/LinuxCompilation.txt	Thu Dec 13 12:37:10 2018 +0100
@@ -115,8 +115,8 @@
 
 
 
-SUPPORTED - Ubuntu 14.04 LTS
-----------------------------
+SUPPORTED - Ubuntu 14.04 LTS and 16.04 LTS
+------------------------------------------
 
 # sudo apt-get install build-essential unzip cmake mercurial \
        	       	       uuid-dev libcurl4-openssl-dev liblua5.1-0-dev \
--- a/OrthancServer/ServerIndex.cpp	Wed Dec 12 15:42:33 2018 +0100
+++ b/OrthancServer/ServerIndex.cpp	Thu Dec 13 12:37:10 2018 +0100
@@ -2248,6 +2248,78 @@
   }
 
 
+  bool ServerIndex::GetAllMainDicomTags(DicomMap& result,
+                                        const std::string& instancePublicId)
+  {
+    result.Clear();
+    
+    boost::mutex::scoped_lock lock(mutex_);
+
+    // Lookup for the requested resource
+    int64_t instance;
+    ResourceType type;
+    if (!db_.LookupResource(instance, type, instancePublicId) ||
+        type != ResourceType_Instance)
+    {
+      return false;
+    }
+    else
+    {
+      DicomMap tmp;
+
+      db_.GetMainDicomTags(tmp, instance);
+      result.Merge(tmp);
+
+      int64_t series;
+      if (!db_.LookupParent(series, instance))
+      {
+        throw OrthancException(ErrorCode_InternalError);
+      }
+
+      tmp.Clear();
+      db_.GetMainDicomTags(tmp, series);
+      result.Merge(tmp);
+
+      int64_t study;
+      if (!db_.LookupParent(study, series))
+      {
+        throw OrthancException(ErrorCode_InternalError);
+      }
+
+      tmp.Clear();
+      db_.GetMainDicomTags(tmp, study);
+      result.Merge(tmp);
+
+#ifndef NDEBUG
+      {
+        // Sanity test to check that all the main DICOM tags from the
+        // patient level are copied at the study level
+        
+        int64_t patient;
+        if (!db_.LookupParent(patient, study))
+        {
+          throw OrthancException(ErrorCode_InternalError);
+        }
+
+        tmp.Clear();
+        db_.GetMainDicomTags(tmp, study);
+
+        std::set<DicomTag> patientTags;
+        tmp.GetTags(patientTags);
+
+        for (std::set<DicomTag>::const_iterator
+               it = patientTags.begin(); it != patientTags.end(); ++it)
+        {
+          assert(result.HasTag(*it));
+        }
+      }
+#endif
+      
+      return true;
+    }
+  }
+
+
   bool ServerIndex::LookupResourceType(ResourceType& type,
                                        const std::string& publicId)
   {
--- a/OrthancServer/ServerIndex.h	Wed Dec 12 15:42:33 2018 +0100
+++ b/OrthancServer/ServerIndex.h	Thu Dec 13 12:37:10 2018 +0100
@@ -275,6 +275,10 @@
                           ResourceType expectedType,
                           ResourceType levelOfInterest);
 
+    // Only applicable at the instance level
+    bool GetAllMainDicomTags(DicomMap& result,
+                             const std::string& instancePublicId);
+
     bool LookupResourceType(ResourceType& type,
                             const std::string& publicId);
 
--- a/UnitTestsSources/DicomMapTests.cpp	Wed Dec 12 15:42:33 2018 +0100
+++ b/UnitTestsSources/DicomMapTests.cpp	Thu Dec 13 12:37:10 2018 +0100
@@ -504,3 +504,44 @@
   //std::cout << toStore.GetJson() << std::endl;
   //a.Print(stdout);
 }
+
+
+
+TEST(DicomMap, ExtractMainDicomTags)
+{
+  DicomMap b;
+  b.SetValue(DICOM_TAG_PATIENT_NAME, "E", false);
+
+  {
+    DicomMap a;
+    a.SetValue(DICOM_TAG_PATIENT_NAME, "A", false);
+    a.SetValue(DICOM_TAG_STUDY_DESCRIPTION, "B", false);
+    a.SetValue(DICOM_TAG_SERIES_DESCRIPTION, "C", false);
+    a.SetValue(DICOM_TAG_NUMBER_OF_FRAMES, "D", false);
+    a.SetValue(DICOM_TAG_SLICE_THICKNESS, "F", false);
+    b.ExtractMainDicomTags(a);
+  }
+
+  ASSERT_EQ(4u, b.GetSize());
+  ASSERT_EQ("A", b.GetValue(DICOM_TAG_PATIENT_NAME).GetContent());
+  ASSERT_EQ("B", b.GetValue(DICOM_TAG_STUDY_DESCRIPTION).GetContent());
+  ASSERT_EQ("C", b.GetValue(DICOM_TAG_SERIES_DESCRIPTION).GetContent());
+  ASSERT_EQ("D", b.GetValue(DICOM_TAG_NUMBER_OF_FRAMES).GetContent());
+  ASSERT_FALSE(b.HasTag(DICOM_TAG_SLICE_THICKNESS));
+
+  b.SetValue(DICOM_TAG_PATIENT_NAME, "G", false);
+
+  {
+    DicomMap a;
+    a.SetValue(DICOM_TAG_PATIENT_NAME, "A", false);
+    a.SetValue(DICOM_TAG_SLICE_THICKNESS, "F", false);
+    b.Merge(a);
+  }
+
+  ASSERT_EQ(5u, b.GetSize());
+  ASSERT_EQ("G", b.GetValue(DICOM_TAG_PATIENT_NAME).GetContent());
+  ASSERT_EQ("B", b.GetValue(DICOM_TAG_STUDY_DESCRIPTION).GetContent());
+  ASSERT_EQ("C", b.GetValue(DICOM_TAG_SERIES_DESCRIPTION).GetContent());
+  ASSERT_EQ("D", b.GetValue(DICOM_TAG_NUMBER_OF_FRAMES).GetContent());
+  ASSERT_EQ("F", b.GetValue(DICOM_TAG_SLICE_THICKNESS).GetContent());
+}