changeset 4684:e3810750dc9d

simplified DicomModification::RelationshipsVisitor
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 08 Jun 2021 14:42:09 +0200
parents 7182f5732480
children 693f049729ba
files OrthancFramework/Sources/DicomParsing/DicomModification.cpp OrthancFramework/Sources/DicomParsing/DicomModification.h
diffstat 2 files changed, 96 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomParsing/DicomModification.cpp	Tue Jun 08 12:37:48 2021 +0200
+++ b/OrthancFramework/Sources/DicomParsing/DicomModification.cpp	Tue Jun 08 14:42:09 2021 +0200
@@ -69,23 +69,14 @@
   {
   private:
     DicomModification&  that_;
-    
-    bool IsEnabled(const DicomTag& tag) const
+
+    // This method is only applicable to first-level tags
+    bool IsManuallyModified(const DicomTag& tag) const
     {
-      return (!that_.IsCleared(tag) &&
-              !that_.IsRemoved(tag) &&
-              !that_.IsReplaced(tag));
-    }
-
-    void RemoveIfEnabled(ParsedDicomFile& dicom,
-                         const DicomTag& tag) const
-    {
-      if (IsEnabled(tag))
-      {
-        dicom.Remove(tag);
-      }
-    }
-                         
+      return (that_.IsCleared(tag) ||
+              that_.IsRemoved(tag) ||
+              that_.IsReplaced(tag));
+    }                         
 
   public:
     explicit RelationshipsVisitor(DicomModification& that) :
@@ -145,56 +136,85 @@
                                ValueRepresentation vr,
                                const std::string& value)
     {
-      // Note that all the tags in "uids_" have the VR UI (unique
-      // identifier), and are considered as strings
-      
-      if (!IsEnabled(tag))
-      {
-        return Action_None;
-      }
-      else if (!parentTags.empty() &&  // Don't anonymize twice the anonymization done by "MapDicomTags()"
-               tag == DICOM_TAG_STUDY_INSTANCE_UID)
-      {
-        newValue = that_.MapDicomIdentifier(value, ResourceType_Study);
-        return Action_Replace;
-      }
-      else if (!parentTags.empty() &&  // Don't anonymize twice the anonymization done by "MapDicomTags()"
-               tag == DICOM_TAG_SERIES_INSTANCE_UID)
+      /**
+       * Note that all the tags in "uids_" have the VR UI (unique
+       * identifier), and are considered as strings.
+       *
+       * Also, the tags "SOP Instance UID", "Series Instance UID" and
+       * "Study Instance UID" are *never* included in "uids_", as they
+       * are separately handed by "MapDicomTags()".
+       **/
+
+      assert(that_.uids_.find(DICOM_TAG_STUDY_INSTANCE_UID) == that_.uids_.end());
+      assert(that_.uids_.find(DICOM_TAG_SERIES_INSTANCE_UID) == that_.uids_.end());
+      assert(that_.uids_.find(DICOM_TAG_SOP_INSTANCE_UID) == that_.uids_.end());
+
+      if (parentTags.empty())
       {
-        newValue = that_.MapDicomIdentifier(value, ResourceType_Series);
-        return Action_Replace;
-      }
-      else if (!parentTags.empty() &&  // Don't anonymize twice the anonymization done by "MapDicomTags()"
-               tag == DICOM_TAG_SOP_INSTANCE_UID)
-      {  
-        newValue = that_.MapDicomIdentifier(value, ResourceType_Instance);
-        return Action_Replace;
-      }
-      else if (that_.uids_.find(tag) != that_.uids_.end())
-      {
-        assert(vr == ValueRepresentation_UniqueIdentifier ||
-               vr == ValueRepresentation_NotSupported /* for older versions of DCMTK */);
-        
-        if (parentTags.size() == 2 &&
-            parentTags[0] == DICOM_TAG_REFERENCED_FRAME_OF_REFERENCE_SEQUENCE &&
-            parentTags[1] == DICOM_TAG_RT_REFERENCED_STUDY_SEQUENCE &&
-            tag == DICOM_TAG_REFERENCED_SOP_INSTANCE_UID)
+        // We are on a first-level tag
+        if (that_.uids_.find(tag) != that_.uids_.end() &&
+            !IsManuallyModified(tag))
         {
-          // in RT-STRUCT, this ReferencedSOPInstanceUID is actually referencing a StudyInstanceUID !!
-          // (observed in many data sets including: https://wiki.cancerimagingarchive.net/display/Public/Lung+CT+Segmentation+Challenge+2017)
-          // tested in test_anonymize_relationships_5
-          newValue = that_.MapDicomIdentifier(value, ResourceType_Study);
+          // This is a first-level UID tag that must be anonymized
+          assert(vr == ValueRepresentation_UniqueIdentifier ||
+                 vr == ValueRepresentation_NotSupported /* for older versions of DCMTK */);
+          newValue = that_.MapDicomIdentifier(value, ResourceType_Instance);
+          return Action_Replace;
         }
         else
         {
-          newValue = that_.MapDicomIdentifier(value, ResourceType_Instance);
+          return Action_None;
         }
-
-        return Action_Replace;
       }
       else
       {
-        return Action_None;
+        // We are within a sequence
+        if (tag == DICOM_TAG_STUDY_INSTANCE_UID)
+        {
+          newValue = that_.MapDicomIdentifier(value, ResourceType_Study);
+          return Action_Replace;
+        }
+        else if (tag == DICOM_TAG_SERIES_INSTANCE_UID)
+        {
+          newValue = that_.MapDicomIdentifier(value, ResourceType_Series);
+          return Action_Replace;
+        }
+        else if (tag == DICOM_TAG_SOP_INSTANCE_UID)
+        {  
+          newValue = that_.MapDicomIdentifier(value, ResourceType_Instance);
+          return Action_Replace;
+        }
+        else if (that_.uids_.find(tag) != that_.uids_.end())
+        {
+          assert(vr == ValueRepresentation_UniqueIdentifier ||
+                 vr == ValueRepresentation_NotSupported /* for older versions of DCMTK */);
+
+          if (parentTags.size() == 2 &&
+              parentTags[0] == DICOM_TAG_REFERENCED_FRAME_OF_REFERENCE_SEQUENCE &&
+              parentTags[1] == DICOM_TAG_RT_REFERENCED_STUDY_SEQUENCE &&
+              tag == DICOM_TAG_REFERENCED_SOP_INSTANCE_UID)
+          {
+            /**
+             * In RT-STRUCT, this ReferencedSOPInstanceUID is actually
+             * referencing a StudyInstanceUID !! (observed in many
+             * data sets including:
+             * https://wiki.cancerimagingarchive.net/display/Public/Lung+CT+Segmentation+Challenge+2017)
+             * Tested in "test_anonymize_relationships_5". Introduced
+             * in: https://hg.orthanc-server.com/orthanc/rev/3513
+             **/
+            newValue = that_.MapDicomIdentifier(value, ResourceType_Study);
+          }
+          else
+          {
+            newValue = that_.MapDicomIdentifier(value, ResourceType_Instance);
+          }
+
+          return Action_Replace;
+        }
+        else
+        {
+          return Action_None;
+        }
       }
     }
 
@@ -202,18 +222,27 @@
     {
       for (SetOfTags::const_iterator it = that_.uids_.begin(); it != that_.uids_.end(); ++it)
       {
-        if (*it != DICOM_TAG_STUDY_INSTANCE_UID &&
-            *it != DICOM_TAG_SERIES_INSTANCE_UID &&
-            *it != DICOM_TAG_SOP_INSTANCE_UID)
+        assert(*it != DICOM_TAG_STUDY_INSTANCE_UID &&
+               *it != DICOM_TAG_SERIES_INSTANCE_UID &&
+               *it != DICOM_TAG_SOP_INSTANCE_UID);
+
+        if (!IsManuallyModified(*it))
         {
-          RemoveIfEnabled(dicom, *it);
+          dicom.Remove(*it);
         }
       }
 
       // The only two sequences with to the "X/Z/U*" rule in the
       // basic profile. They were already present in Orthanc 1.9.3.
-      RemoveIfEnabled(dicom, DICOM_TAG_REFERENCED_IMAGE_SEQUENCE);
-      RemoveIfEnabled(dicom, DICOM_TAG_SOURCE_IMAGE_SEQUENCE);
+      if (!IsManuallyModified(DICOM_TAG_REFERENCED_IMAGE_SEQUENCE))
+      {
+        dicom.Remove(DICOM_TAG_REFERENCED_IMAGE_SEQUENCE);
+      }
+      
+      if (!IsManuallyModified(DICOM_TAG_SOURCE_IMAGE_SEQUENCE))
+      {
+        dicom.Remove(DICOM_TAG_SOURCE_IMAGE_SEQUENCE);
+      }
     }
   };
 
--- a/OrthancFramework/Sources/DicomParsing/DicomModification.h	Tue Jun 08 12:37:48 2021 +0200
+++ b/OrthancFramework/Sources/DicomParsing/DicomModification.h	Tue Jun 08 14:42:09 2021 +0200
@@ -106,8 +106,6 @@
     SetOfTags removals_;
     SetOfTags clearings_;
     Replacements replacements_;
-    SetOfTags uids_;                // New in Orthanc 1.9.4
-    RemovedRanges removedRanges_;   // New in Orthanc 1.9.4
     bool removePrivateTags_;
     ResourceType level_;
     UidMap uidMap_;
@@ -123,6 +121,10 @@
 
     IDicomIdentifierGenerator* identifierGenerator_;
 
+    // New in Orthanc 1.9.4
+    SetOfTags uids_;
+    RemovedRanges removedRanges_;
+
     std::string MapDicomIdentifier(const std::string& original,
                                    ResourceType level);