Mercurial > hg > orthanc
comparison Core/DicomParsing/DicomModification.cpp @ 3513:7db879b014ff
Fix lost relationships between CT and RT-STRUCT during anonymization
author | amazy |
---|---|
date | Thu, 05 Sep 2019 13:11:35 +0200 |
parents | 90b4a5001c24 |
children | 94f4a18a79cc |
comparison
equal
deleted
inserted
replaced
3512:4bced7d1ec20 | 3513:7db879b014ff |
---|---|
133 { | 133 { |
134 if (!IsEnabled(tag)) | 134 if (!IsEnabled(tag)) |
135 { | 135 { |
136 return Action_None; | 136 return Action_None; |
137 } | 137 } |
138 else if (tag == DICOM_TAG_FRAME_OF_REFERENCE_UID || | 138 else if (parentTags.size() == 2 && |
139 parentTags[0] == DICOM_TAG_REFERENCED_FRAME_OF_REFERENCE_SEQUENCE && | |
140 parentTags[1] == DICOM_TAG_RT_REFERENCED_STUDY_SEQUENCE && | |
141 tag == DICOM_TAG_REFERENCED_SOP_INSTANCE_UID) | |
142 { | |
143 // in RT-STRUCT, this ReferencedSOPInstanceUID is actually referencing a StudyInstanceUID !! | |
144 // (observed in many data sets including: https://wiki.cancerimagingarchive.net/display/Public/Lung+CT+Segmentation+Challenge+2017) | |
145 // tested in test_anonymize_relationships_5 | |
146 newValue = that_.MapDicomIdentifier(Toolbox::StripSpaces(value), ResourceType_Study); | |
147 return Action_Replace; | |
148 } | |
149 else if (tag == DICOM_TAG_FRAME_OF_REFERENCE_UID || | |
139 tag == DICOM_TAG_REFERENCED_FRAME_OF_REFERENCE_UID || | 150 tag == DICOM_TAG_REFERENCED_FRAME_OF_REFERENCE_UID || |
140 tag == DICOM_TAG_REFERENCED_SOP_INSTANCE_UID || | 151 tag == DICOM_TAG_REFERENCED_SOP_INSTANCE_UID || |
141 tag == DICOM_TAG_RELATED_FRAME_OF_REFERENCE_UID) | 152 tag == DICOM_TAG_RELATED_FRAME_OF_REFERENCE_UID) |
142 { | 153 { |
143 newValue = that_.MapDicomIdentifier(Toolbox::StripSpaces(value), ResourceType_Instance); | 154 newValue = that_.MapDicomIdentifier(Toolbox::StripSpaces(value), ResourceType_Instance); |
151 return Action_Replace; | 162 return Action_Replace; |
152 } | 163 } |
153 else if (parentTags.size() == 2 && | 164 else if (parentTags.size() == 2 && |
154 parentTags[0] == DICOM_TAG_CURRENT_REQUESTED_PROCEDURE_EVIDENCE_SEQUENCE && | 165 parentTags[0] == DICOM_TAG_CURRENT_REQUESTED_PROCEDURE_EVIDENCE_SEQUENCE && |
155 parentTags[1] == DICOM_TAG_REFERENCED_SERIES_SEQUENCE && | 166 parentTags[1] == DICOM_TAG_REFERENCED_SERIES_SEQUENCE && |
167 tag == DICOM_TAG_SERIES_INSTANCE_UID) | |
168 { | |
169 newValue = that_.MapDicomIdentifier(Toolbox::StripSpaces(value), ResourceType_Series); | |
170 return Action_Replace; | |
171 } | |
172 else if (parentTags.size() == 3 && | |
173 parentTags[0] == DICOM_TAG_REFERENCED_FRAME_OF_REFERENCE_SEQUENCE && | |
174 parentTags[1] == DICOM_TAG_RT_REFERENCED_STUDY_SEQUENCE && | |
175 parentTags[2] == DICOM_TAG_RT_REFERENCED_SERIES_SEQUENCE && | |
156 tag == DICOM_TAG_SERIES_INSTANCE_UID) | 176 tag == DICOM_TAG_SERIES_INSTANCE_UID) |
157 { | 177 { |
158 newValue = that_.MapDicomIdentifier(Toolbox::StripSpaces(value), ResourceType_Series); | 178 newValue = that_.MapDicomIdentifier(Toolbox::StripSpaces(value), ResourceType_Series); |
159 return Action_Replace; | 179 return Action_Replace; |
160 } | 180 } |
247 delete it->second; | 267 delete it->second; |
248 replacements_.erase(it); | 268 replacements_.erase(it); |
249 } | 269 } |
250 } | 270 } |
251 | 271 |
252 | 272 void DicomModification::RegisterMappedDicomIdentifier(const std::string& original, |
273 const std::string& mapped, | |
274 ResourceType level) | |
275 { | |
276 UidMap::const_iterator previous = uidMap_.find(std::make_pair(level, original)); | |
277 | |
278 if (previous == uidMap_.end()) | |
279 { | |
280 uidMap_.insert(std::make_pair(std::make_pair(level, original), mapped)); | |
281 } | |
282 } | |
253 | 283 |
254 std::string DicomModification::MapDicomIdentifier(const std::string& original, | 284 std::string DicomModification::MapDicomIdentifier(const std::string& original, |
255 ResourceType level) | 285 ResourceType level) |
256 { | 286 { |
257 std::string mapped; | 287 std::string mapped; |
974 { | 1004 { |
975 throw OrthancException(ErrorCode_BadRequest, | 1005 throw OrthancException(ErrorCode_BadRequest, |
976 "When modifying an instance, the parent SeriesInstanceUID cannot be manually modified"); | 1006 "When modifying an instance, the parent SeriesInstanceUID cannot be manually modified"); |
977 } | 1007 } |
978 | 1008 |
979 | |
980 // (0) Create a summary of the source file, if a custom generator | 1009 // (0) Create a summary of the source file, if a custom generator |
981 // is provided | 1010 // is provided |
982 if (identifierGenerator_ != NULL) | 1011 if (identifierGenerator_ != NULL) |
983 { | 1012 { |
984 toModify.ExtractDicomSummary(currentSource_); | 1013 toModify.ExtractDicomSummary(currentSource_); |
985 } | 1014 } |
986 | 1015 |
987 | 1016 // (1) Make sure the relationships are updated with the ids that we force too |
988 // (1) Remove the private tags, if need be | 1017 // i.e: an RT-STRUCT is referencing its own StudyInstanceUID |
1018 if (isAnonymization_ && updateReferencedRelationships_) | |
1019 { | |
1020 if (IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID)) | |
1021 { | |
1022 std::string original; | |
1023 std::string replacement = GetReplacementAsString(DICOM_TAG_STUDY_INSTANCE_UID); | |
1024 toModify.GetTagValue(original, DICOM_TAG_STUDY_INSTANCE_UID); | |
1025 RegisterMappedDicomIdentifier(original, replacement, ResourceType_Study); | |
1026 } | |
1027 | |
1028 if (IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID)) | |
1029 { | |
1030 std::string original; | |
1031 std::string replacement = GetReplacementAsString(DICOM_TAG_SERIES_INSTANCE_UID); | |
1032 toModify.GetTagValue(original, DICOM_TAG_SERIES_INSTANCE_UID); | |
1033 RegisterMappedDicomIdentifier(original, replacement, ResourceType_Series); | |
1034 } | |
1035 | |
1036 if (IsReplaced(DICOM_TAG_SOP_INSTANCE_UID)) | |
1037 { | |
1038 std::string original; | |
1039 std::string replacement = GetReplacementAsString(DICOM_TAG_SOP_INSTANCE_UID); | |
1040 toModify.GetTagValue(original, DICOM_TAG_SOP_INSTANCE_UID); | |
1041 RegisterMappedDicomIdentifier(original, replacement, ResourceType_Instance); | |
1042 } | |
1043 } | |
1044 | |
1045 | |
1046 // (2) Remove the private tags, if need be | |
989 if (removePrivateTags_) | 1047 if (removePrivateTags_) |
990 { | 1048 { |
991 toModify.RemovePrivateTags(privateTagsToKeep_); | 1049 toModify.RemovePrivateTags(privateTagsToKeep_); |
992 } | 1050 } |
993 | 1051 |
994 // (2) Clear the tags specified by the user | 1052 // (3) Clear the tags specified by the user |
995 for (SetOfTags::const_iterator it = clearings_.begin(); | 1053 for (SetOfTags::const_iterator it = clearings_.begin(); |
996 it != clearings_.end(); ++it) | 1054 it != clearings_.end(); ++it) |
997 { | 1055 { |
998 toModify.Clear(*it, true /* only clear if the tag exists in the original file */); | 1056 toModify.Clear(*it, true /* only clear if the tag exists in the original file */); |
999 } | 1057 } |
1000 | 1058 |
1001 // (3) Remove the tags specified by the user | 1059 // (4) Remove the tags specified by the user |
1002 for (SetOfTags::const_iterator it = removals_.begin(); | 1060 for (SetOfTags::const_iterator it = removals_.begin(); |
1003 it != removals_.end(); ++it) | 1061 it != removals_.end(); ++it) |
1004 { | 1062 { |
1005 toModify.Remove(*it); | 1063 toModify.Remove(*it); |
1006 } | 1064 } |
1007 | 1065 |
1008 // (4) Replace the tags | 1066 // (5) Replace the tags |
1009 for (Replacements::const_iterator it = replacements_.begin(); | 1067 for (Replacements::const_iterator it = replacements_.begin(); |
1010 it != replacements_.end(); ++it) | 1068 it != replacements_.end(); ++it) |
1011 { | 1069 { |
1012 toModify.Replace(it->first, *it->second, true /* decode data URI scheme */, DicomReplaceMode_InsertIfAbsent); | 1070 toModify.Replace(it->first, *it->second, true /* decode data URI scheme */, DicomReplaceMode_InsertIfAbsent); |
1013 } | 1071 } |
1014 | 1072 |
1015 // (5) Update the DICOM identifiers | 1073 // (6) Update the DICOM identifiers |
1016 if (level_ <= ResourceType_Study && | 1074 if (level_ <= ResourceType_Study && |
1017 !IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID)) | 1075 !IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID)) |
1018 { | 1076 { |
1019 if (keepStudyInstanceUid_) | 1077 if (keepStudyInstanceUid_) |
1020 { | 1078 { |
1043 !IsReplaced(DICOM_TAG_SOP_INSTANCE_UID)) | 1101 !IsReplaced(DICOM_TAG_SOP_INSTANCE_UID)) |
1044 { | 1102 { |
1045 MapDicomTags(toModify, ResourceType_Instance); | 1103 MapDicomTags(toModify, ResourceType_Instance); |
1046 } | 1104 } |
1047 | 1105 |
1048 // (6) Update the "referenced" relationships in the case of an anonymization | 1106 // (7) Update the "referenced" relationships in the case of an anonymization |
1049 if (isAnonymization_) | 1107 if (isAnonymization_) |
1050 { | 1108 { |
1051 RelationshipsVisitor visitor(*this); | 1109 RelationshipsVisitor visitor(*this); |
1052 | 1110 |
1053 if (updateReferencedRelationships_) | 1111 if (updateReferencedRelationships_) |