changeset 4933:312c6f4da888 more-tags

adding MainDicomTags signatures
author Alain Mazy <am@osimis.io>
date Wed, 09 Mar 2022 12:16:45 +0100
parents b7ce2bb6b881
children 94a7b681b340
files OrthancFramework/Sources/DicomFormat/DicomMap.cpp OrthancFramework/Sources/DicomFormat/DicomMap.h OrthancFramework/UnitTestsSources/DicomMapTests.cpp
diffstat 3 files changed, 94 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomFormat/DicomMap.cpp	Wed Mar 09 11:17:08 2022 +0100
+++ b/OrthancFramework/Sources/DicomFormat/DicomMap.cpp	Wed Mar 09 12:16:45 2022 +0100
@@ -26,6 +26,7 @@
 
 #include <stdio.h>
 #include <memory>
+#include <boost/algorithm/string/join.hpp>
 
 #include "../Compatibility.h"
 #include "../Endianness.h"
@@ -49,6 +50,15 @@
   }
 
 
+  // WARNING: the DEFAULT list of main dicom tags below are the list as they 
+  // were in Orthanc 1.10 before we introduced the dynamic main dicom tags.
+  // This list has not changed since Orthanc 1.4.2 and had a single change since
+  // Orthanc 0.9.5.
+  // These lists have a specific signature.  When a resource does not have
+  // the metadata "MainDicomTagsSignature", we'll assume that they were stored
+  // with an Orthanc prior to 1.11.  It is therefore very important that you never
+  // change these lists !
+
   static const MainDicomTag DEFAULT_PATIENT_MAIN_DICOM_TAGS[] =
   {
     // { DicomTag(0x0010, 0x1010), "PatientAge" },
@@ -163,6 +173,9 @@
     std::map<ResourceType, std::set<DicomTag> > mainDicomTagsByLevel_;
     std::set<DicomTag> allMainDicomTags_;
 
+    std::map<ResourceType, std::string> signatures_;
+    std::map<ResourceType, std::string> defaultSignatures_;
+
     MainDicomTagsConfiguration()
     {
       ResetDefaultMainDicomTags();
@@ -180,6 +193,27 @@
       LoadDefaultMainDicomTags(ResourceType_Study);
       LoadDefaultMainDicomTags(ResourceType_Series);
       LoadDefaultMainDicomTags(ResourceType_Instance);
+
+      defaultSignatures_[ResourceType_Patient] = signatures_[ResourceType_Patient];
+      defaultSignatures_[ResourceType_Study] = signatures_[ResourceType_Study];
+      defaultSignatures_[ResourceType_Series] = signatures_[ResourceType_Series];
+      defaultSignatures_[ResourceType_Instance] = signatures_[ResourceType_Instance];
+    }
+
+    std::string ComputeSignature(const std::set<DicomTag>& tags)
+    {
+      // std::set are sorted by default (which is important for us !)
+      std::set<std::string> tagsIds;
+      for (std::set<DicomTag>::const_iterator it = tags.begin(); it != tags.end(); it++)
+      {
+        tagsIds.insert(it->Format());
+      }
+
+      std::string signatureText = boost::algorithm::join(tagsIds, "|");
+      std::string signatureMD5;
+      Toolbox::ComputeMD5(signatureMD5, signatureText);
+
+      return signatureMD5;
     }
 
     void LoadDefaultMainDicomTags(ResourceType level)
@@ -249,6 +283,7 @@
       mainDicomTagsByName_[level][name] = DicomTag2(tag);
       mainDicomTagsByLevel_[level].insert(tag);
       allMainDicomTags_.insert(tag);
+      signatures_[level] = ComputeSignature(GetMainDicomTagsByLevel(level));
     }
 
     const std::map<DicomTag, std::string>& GetMainDicomTags(ResourceType level) const
@@ -276,6 +311,21 @@
     {
       return allMainDicomTags_;
     }
+
+    const std::string& GetMainDicomTagsSignature(ResourceType level)
+    {
+      assert(signatures_.find(level) != signatures_.end());
+
+      return signatures_[level];
+    }
+
+    const std::string& GetDefaultMainDicomTagsSignature(ResourceType level)
+    {
+      assert(defaultSignatures_.find(level) != defaultSignatures_.end());
+
+      return defaultSignatures_[level];
+    }
+
   };
 
 
@@ -589,6 +639,16 @@
     DicomMap::MainDicomTagsConfiguration::GetInstance().ResetDefaultMainDicomTags();
   }
 
+  const std::string& DicomMap::GetMainDicomTagsSignature(ResourceType level)
+  {
+    return DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTagsSignature(level);
+  }
+
+  const std::string& DicomMap::GetDefaultMainDicomTagsSignature(ResourceType level)
+  {
+    return DicomMap::MainDicomTagsConfiguration::GetInstance().GetDefaultMainDicomTagsSignature(level);
+  }
+
   void DicomMap::GetTags(std::set<DicomTag>& tags) const
   {
     tags.clear();
--- a/OrthancFramework/Sources/DicomFormat/DicomMap.h	Wed Mar 09 11:17:08 2022 +0100
+++ b/OrthancFramework/Sources/DicomFormat/DicomMap.h	Wed Mar 09 12:16:45 2022 +0100
@@ -135,6 +135,11 @@
 
     static const std::set<DicomTag>& GetMainDicomTags(ResourceType level);
 
+    // returns a string uniquely identifying the list of main dicom tags for a level
+    static const std::string& GetMainDicomTagsSignature(ResourceType level);
+
+    static const std::string& GetDefaultMainDicomTagsSignature(ResourceType level);
+
     static const std::set<DicomTag>& GetAllMainDicomTags();
 
     // adds a main dicom tag to the definition of main dicom tags for each level.
--- a/OrthancFramework/UnitTestsSources/DicomMapTests.cpp	Wed Mar 09 11:17:08 2022 +0100
+++ b/OrthancFramework/UnitTestsSources/DicomMapTests.cpp	Wed Mar 09 12:16:45 2022 +0100
@@ -138,6 +138,35 @@
     // adding another tag with same name should throw
     ASSERT_THROW(DicomMap::AddMainDicomTag(DICOM_TAG_BITS_STORED, "BitsAllocated", ResourceType_Instance), OrthancException);
   }
+
+  TEST_F(DicomMapMainTagsTests, Signatures)
+  {
+    std::string defaultPatientSignature = DicomMap::GetDefaultMainDicomTagsSignature(ResourceType_Patient);
+    std::string defaultStudySignature = DicomMap::GetDefaultMainDicomTagsSignature(ResourceType_Study);
+    std::string defaultSeriesSignature = DicomMap::GetDefaultMainDicomTagsSignature(ResourceType_Series);
+    std::string defaultInstanceSignature = DicomMap::GetDefaultMainDicomTagsSignature(ResourceType_Instance);
+
+    ASSERT_NE(defaultInstanceSignature, defaultPatientSignature);
+    ASSERT_NE(defaultSeriesSignature, defaultStudySignature);
+    ASSERT_NE(defaultSeriesSignature, defaultPatientSignature);
+
+    std::string patientSignature = DicomMap::GetMainDicomTagsSignature(ResourceType_Patient);
+    std::string studySignature = DicomMap::GetMainDicomTagsSignature(ResourceType_Study);
+    std::string seriesSignature = DicomMap::GetMainDicomTagsSignature(ResourceType_Series);
+    std::string instanceSignature = DicomMap::GetMainDicomTagsSignature(ResourceType_Instance);
+
+    // at start, default and current signature should be equal
+    ASSERT_EQ(defaultPatientSignature, patientSignature);
+    ASSERT_EQ(defaultStudySignature, studySignature);
+    ASSERT_EQ(defaultSeriesSignature, seriesSignature);
+    ASSERT_EQ(defaultInstanceSignature, instanceSignature);
+
+    DicomMap::AddMainDicomTag(DICOM_TAG_BITS_ALLOCATED, "BitsAllocated", ResourceType_Instance);
+    instanceSignature = DicomMap::GetMainDicomTagsSignature(ResourceType_Instance);
+    
+    ASSERT_NE(defaultInstanceSignature, instanceSignature);
+  }
+
 }
 
 TEST(DicomMap, Tags)