diff OrthancFramework/Sources/DicomParsing/DicomModification.cpp @ 4685:693f049729ba

New versions of Keep(), Remove() and Replace() in DicomModification that use DicomPath
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 08 Jun 2021 18:28:57 +0200
parents e3810750dc9d
children fcd2dc7c8f31
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomParsing/DicomModification.cpp	Tue Jun 08 14:42:09 2021 +0200
+++ b/OrthancFramework/Sources/DicomParsing/DicomModification.cpp	Tue Jun 08 18:28:57 2021 +0200
@@ -169,6 +169,22 @@
       else
       {
         // We are within a sequence
+
+        if (!that_.keepSequences_.empty())
+        {
+          // New in Orthanc 1.9.4 - Solves issue LSD-629
+          DicomPath path(parentTags, parentIndexes, tag);
+          
+          for (ListOfPaths::const_iterator it = that_.keepSequences_.begin();
+               it != that_.keepSequences_.end(); ++it)
+          {
+            if (DicomPath::IsMatch(*it, path))
+            {
+              return Action_None;
+            }
+          }
+        }
+
         if (tag == DICOM_TAG_STUDY_INSTANCE_UID)
         {
           newValue = that_.MapDicomIdentifier(value, ResourceType_Study);
@@ -247,19 +263,15 @@
   };
 
 
-  bool DicomModification::CancelReplacement(const DicomTag& tag)
+  void DicomModification::CancelReplacement(const DicomTag& tag)
   {
     Replacements::iterator it = replacements_.find(tag);
     
     if (it != replacements_.end())
     {
+      assert(it->second != NULL);
       delete it->second;
       replacements_.erase(it);
-      return true;
-    }
-    else
-    {
-      return false;
     }
   }
 
@@ -271,6 +283,7 @@
 
     if (it != replacements_.end())
     {
+      assert(it->second != NULL);
       delete it->second;
       it->second = NULL;   // In the case of an exception during the clone
       it->second = new Json::Value(value);  // Clone
@@ -287,10 +300,21 @@
     for (Replacements::iterator it = replacements_.begin();
          it != replacements_.end(); ++it)
     {
+      assert(it->second != NULL);
       delete it->second;
     }
 
     replacements_.clear();
+
+    for (SequenceReplacements::iterator it = sequenceReplacements_.begin();
+         it != sequenceReplacements_.end(); ++it)
+    {
+      assert(*it != NULL);
+      assert((*it)->GetPath().GetPrefixLength() > 0);
+      delete *it;
+    }
+
+    sequenceReplacements_.clear();
   }
 
 
@@ -298,13 +322,17 @@
   {
     Replacements::iterator it = replacements_.find(DICOM_TAG_DEIDENTIFICATION_METHOD);
 
-    if (it != replacements_.end() &&
-        (it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2008 ||
-         it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2017c ||
-         it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2021b))
+    if (it != replacements_.end())
     {
-      delete it->second;
-      replacements_.erase(it);
+      assert(it->second != NULL);
+
+      if (it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2008 ||
+          it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2017c ||
+          it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2021b)
+      {
+        delete it->second;
+        replacements_.erase(it);
+      }
     }
   }
 
@@ -413,14 +441,11 @@
 
   void DicomModification::Keep(const DicomTag& tag)
   {
-    bool wasRemoved = IsRemoved(tag);
-    bool wasCleared = IsCleared(tag);
-    
     removals_.erase(tag);
     clearings_.erase(tag);
     uids_.erase(tag);
 
-    bool wasReplaced = CancelReplacement(tag);
+    CancelReplacement(tag);
 
     if (tag == DICOM_TAG_STUDY_INSTANCE_UID)
     {
@@ -438,12 +463,6 @@
     {
       privateTagsToKeep_.insert(tag);
     }
-    else if (!wasRemoved &&
-             !wasReplaced &&
-             !wasCleared)
-    {
-      LOG(WARNING) << "Marking this tag as to be kept has no effect: " << tag.Format();
-    }
 
     MarkNotOrthancAnonymization();
   }
@@ -528,6 +547,7 @@
     }
     else
     {
+      assert(it->second != NULL);
       return *it->second;
     } 
   }
@@ -727,6 +747,8 @@
     level_ = ResourceType_Patient;
     uidMap_.clear();
     privateTagsToKeep_.clear();
+    keepSequences_.clear();
+    removeSequences_.clear();    
 
     switch (version)
     {
@@ -937,11 +959,29 @@
     for (Replacements::const_iterator it = replacements_.begin(); 
          it != replacements_.end(); ++it)
     {
+      assert(it->second != NULL);
       toModify.Replace(it->first, *it->second, true /* decode data URI scheme */,
                        DicomReplaceMode_InsertIfAbsent, privateCreator_);
     }
 
-    // (6) Update the DICOM identifiers
+    // (6) New in Orthanc 1.9.4: Apply modifications to subsequences
+    for (ListOfPaths::const_iterator it = removeSequences_.begin();
+         it != removeSequences_.end(); ++it)
+    {
+      assert(it->GetPrefixLength() > 0);
+      toModify.RemovePath(*it);
+    }
+
+    for (SequenceReplacements::const_iterator it = sequenceReplacements_.begin();
+         it != sequenceReplacements_.end(); ++it)
+    {
+      assert(*it != NULL);
+      assert((*it)->GetPath().GetPrefixLength() > 0);
+      toModify.ReplacePath((*it)->GetPath(), (*it)->GetValue(), true /* decode data URI scheme */,
+                           DicomReplaceMode_InsertIfAbsent, privateCreator_);
+    }
+
+    // (7) Update the DICOM identifiers
     if (level_ <= ResourceType_Study &&
         !IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID))
     {
@@ -981,7 +1021,7 @@
       }
     }
 
-    // (7) Update the "referenced" relationships in the case of an anonymization
+    // (8) Update the "referenced" relationships in the case of an anonymization
     if (isAnonymization_)
     {
       RelationshipsVisitor visitor(*this);
@@ -1089,7 +1129,7 @@
                                "requires the \"Force\" option to be set to true");
       }
 
-      target.Replace(tag, value, false);
+      target.Replace(tag, value, false /* not safe for anonymization */);
 
       LOG(TRACE) << "Replace: " << name << " (" << tag.Format() 
                  << ") == " << value.toStyledString();
@@ -1483,4 +1523,50 @@
   {
     return privateCreator_;
   }
+
+
+  void DicomModification::Keep(const DicomPath& path)
+  {
+    if (path.GetPrefixLength() == 0)
+    {
+      Keep(path.GetFinalTag());
+    }
+
+    keepSequences_.push_back(path);
+    MarkNotOrthancAnonymization();
+  }
+  
+
+  void DicomModification::Remove(const DicomPath& path)
+  {
+    if (path.GetPrefixLength() == 0)
+    {
+      Remove(path.GetFinalTag());
+    }
+    else
+    {
+      removeSequences_.push_back(path);
+      MarkNotOrthancAnonymization();
+    }
+  }
+  
+
+  void DicomModification::Replace(const DicomPath& path,
+                                  const Json::Value& value,
+                                  bool safeForAnonymization)
+  {
+    if (path.GetPrefixLength() == 0)
+    {
+      Replace(path.GetFinalTag(), value, safeForAnonymization);
+    }
+    else
+    {
+      sequenceReplacements_.push_back(new SequenceReplacement(path, value));
+
+      if (!safeForAnonymization)
+      {
+        MarkNotOrthancAnonymization();
+      }
+    }
+  }
 }