Mercurial > hg > orthanc
comparison OrthancFramework/Sources/DicomParsing/DicomModification.cpp @ 4684:e3810750dc9d
simplified DicomModification::RelationshipsVisitor
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 08 Jun 2021 14:42:09 +0200 |
parents | 2e850edf03d6 |
children | 693f049729ba |
comparison
equal
deleted
inserted
replaced
4683:7182f5732480 | 4684:e3810750dc9d |
---|---|
67 | 67 |
68 class DicomModification::RelationshipsVisitor : public ITagVisitor | 68 class DicomModification::RelationshipsVisitor : public ITagVisitor |
69 { | 69 { |
70 private: | 70 private: |
71 DicomModification& that_; | 71 DicomModification& that_; |
72 | 72 |
73 bool IsEnabled(const DicomTag& tag) const | 73 // This method is only applicable to first-level tags |
74 { | 74 bool IsManuallyModified(const DicomTag& tag) const |
75 return (!that_.IsCleared(tag) && | 75 { |
76 !that_.IsRemoved(tag) && | 76 return (that_.IsCleared(tag) || |
77 !that_.IsReplaced(tag)); | 77 that_.IsRemoved(tag) || |
78 } | 78 that_.IsReplaced(tag)); |
79 | 79 } |
80 void RemoveIfEnabled(ParsedDicomFile& dicom, | |
81 const DicomTag& tag) const | |
82 { | |
83 if (IsEnabled(tag)) | |
84 { | |
85 dicom.Remove(tag); | |
86 } | |
87 } | |
88 | |
89 | 80 |
90 public: | 81 public: |
91 explicit RelationshipsVisitor(DicomModification& that) : | 82 explicit RelationshipsVisitor(DicomModification& that) : |
92 that_(that) | 83 that_(that) |
93 { | 84 { |
143 const std::vector<size_t>& parentIndexes, | 134 const std::vector<size_t>& parentIndexes, |
144 const DicomTag& tag, | 135 const DicomTag& tag, |
145 ValueRepresentation vr, | 136 ValueRepresentation vr, |
146 const std::string& value) | 137 const std::string& value) |
147 { | 138 { |
148 // Note that all the tags in "uids_" have the VR UI (unique | 139 /** |
149 // identifier), and are considered as strings | 140 * Note that all the tags in "uids_" have the VR UI (unique |
150 | 141 * identifier), and are considered as strings. |
151 if (!IsEnabled(tag)) | 142 * |
152 { | 143 * Also, the tags "SOP Instance UID", "Series Instance UID" and |
153 return Action_None; | 144 * "Study Instance UID" are *never* included in "uids_", as they |
154 } | 145 * are separately handed by "MapDicomTags()". |
155 else if (!parentTags.empty() && // Don't anonymize twice the anonymization done by "MapDicomTags()" | 146 **/ |
156 tag == DICOM_TAG_STUDY_INSTANCE_UID) | 147 |
157 { | 148 assert(that_.uids_.find(DICOM_TAG_STUDY_INSTANCE_UID) == that_.uids_.end()); |
158 newValue = that_.MapDicomIdentifier(value, ResourceType_Study); | 149 assert(that_.uids_.find(DICOM_TAG_SERIES_INSTANCE_UID) == that_.uids_.end()); |
159 return Action_Replace; | 150 assert(that_.uids_.find(DICOM_TAG_SOP_INSTANCE_UID) == that_.uids_.end()); |
160 } | 151 |
161 else if (!parentTags.empty() && // Don't anonymize twice the anonymization done by "MapDicomTags()" | 152 if (parentTags.empty()) |
162 tag == DICOM_TAG_SERIES_INSTANCE_UID) | 153 { |
163 { | 154 // We are on a first-level tag |
164 newValue = that_.MapDicomIdentifier(value, ResourceType_Series); | 155 if (that_.uids_.find(tag) != that_.uids_.end() && |
165 return Action_Replace; | 156 !IsManuallyModified(tag)) |
166 } | |
167 else if (!parentTags.empty() && // Don't anonymize twice the anonymization done by "MapDicomTags()" | |
168 tag == DICOM_TAG_SOP_INSTANCE_UID) | |
169 { | |
170 newValue = that_.MapDicomIdentifier(value, ResourceType_Instance); | |
171 return Action_Replace; | |
172 } | |
173 else if (that_.uids_.find(tag) != that_.uids_.end()) | |
174 { | |
175 assert(vr == ValueRepresentation_UniqueIdentifier || | |
176 vr == ValueRepresentation_NotSupported /* for older versions of DCMTK */); | |
177 | |
178 if (parentTags.size() == 2 && | |
179 parentTags[0] == DICOM_TAG_REFERENCED_FRAME_OF_REFERENCE_SEQUENCE && | |
180 parentTags[1] == DICOM_TAG_RT_REFERENCED_STUDY_SEQUENCE && | |
181 tag == DICOM_TAG_REFERENCED_SOP_INSTANCE_UID) | |
182 { | 157 { |
183 // in RT-STRUCT, this ReferencedSOPInstanceUID is actually referencing a StudyInstanceUID !! | 158 // This is a first-level UID tag that must be anonymized |
184 // (observed in many data sets including: https://wiki.cancerimagingarchive.net/display/Public/Lung+CT+Segmentation+Challenge+2017) | 159 assert(vr == ValueRepresentation_UniqueIdentifier || |
185 // tested in test_anonymize_relationships_5 | 160 vr == ValueRepresentation_NotSupported /* for older versions of DCMTK */); |
186 newValue = that_.MapDicomIdentifier(value, ResourceType_Study); | 161 newValue = that_.MapDicomIdentifier(value, ResourceType_Instance); |
162 return Action_Replace; | |
187 } | 163 } |
188 else | 164 else |
189 { | 165 { |
166 return Action_None; | |
167 } | |
168 } | |
169 else | |
170 { | |
171 // We are within a sequence | |
172 if (tag == DICOM_TAG_STUDY_INSTANCE_UID) | |
173 { | |
174 newValue = that_.MapDicomIdentifier(value, ResourceType_Study); | |
175 return Action_Replace; | |
176 } | |
177 else if (tag == DICOM_TAG_SERIES_INSTANCE_UID) | |
178 { | |
179 newValue = that_.MapDicomIdentifier(value, ResourceType_Series); | |
180 return Action_Replace; | |
181 } | |
182 else if (tag == DICOM_TAG_SOP_INSTANCE_UID) | |
183 { | |
190 newValue = that_.MapDicomIdentifier(value, ResourceType_Instance); | 184 newValue = that_.MapDicomIdentifier(value, ResourceType_Instance); |
185 return Action_Replace; | |
191 } | 186 } |
192 | 187 else if (that_.uids_.find(tag) != that_.uids_.end()) |
193 return Action_Replace; | 188 { |
194 } | 189 assert(vr == ValueRepresentation_UniqueIdentifier || |
195 else | 190 vr == ValueRepresentation_NotSupported /* for older versions of DCMTK */); |
196 { | 191 |
197 return Action_None; | 192 if (parentTags.size() == 2 && |
193 parentTags[0] == DICOM_TAG_REFERENCED_FRAME_OF_REFERENCE_SEQUENCE && | |
194 parentTags[1] == DICOM_TAG_RT_REFERENCED_STUDY_SEQUENCE && | |
195 tag == DICOM_TAG_REFERENCED_SOP_INSTANCE_UID) | |
196 { | |
197 /** | |
198 * In RT-STRUCT, this ReferencedSOPInstanceUID is actually | |
199 * referencing a StudyInstanceUID !! (observed in many | |
200 * data sets including: | |
201 * https://wiki.cancerimagingarchive.net/display/Public/Lung+CT+Segmentation+Challenge+2017) | |
202 * Tested in "test_anonymize_relationships_5". Introduced | |
203 * in: https://hg.orthanc-server.com/orthanc/rev/3513 | |
204 **/ | |
205 newValue = that_.MapDicomIdentifier(value, ResourceType_Study); | |
206 } | |
207 else | |
208 { | |
209 newValue = that_.MapDicomIdentifier(value, ResourceType_Instance); | |
210 } | |
211 | |
212 return Action_Replace; | |
213 } | |
214 else | |
215 { | |
216 return Action_None; | |
217 } | |
198 } | 218 } |
199 } | 219 } |
200 | 220 |
201 void RemoveRelationships(ParsedDicomFile& dicom) const | 221 void RemoveRelationships(ParsedDicomFile& dicom) const |
202 { | 222 { |
203 for (SetOfTags::const_iterator it = that_.uids_.begin(); it != that_.uids_.end(); ++it) | 223 for (SetOfTags::const_iterator it = that_.uids_.begin(); it != that_.uids_.end(); ++it) |
204 { | 224 { |
205 if (*it != DICOM_TAG_STUDY_INSTANCE_UID && | 225 assert(*it != DICOM_TAG_STUDY_INSTANCE_UID && |
206 *it != DICOM_TAG_SERIES_INSTANCE_UID && | 226 *it != DICOM_TAG_SERIES_INSTANCE_UID && |
207 *it != DICOM_TAG_SOP_INSTANCE_UID) | 227 *it != DICOM_TAG_SOP_INSTANCE_UID); |
228 | |
229 if (!IsManuallyModified(*it)) | |
208 { | 230 { |
209 RemoveIfEnabled(dicom, *it); | 231 dicom.Remove(*it); |
210 } | 232 } |
211 } | 233 } |
212 | 234 |
213 // The only two sequences with to the "X/Z/U*" rule in the | 235 // The only two sequences with to the "X/Z/U*" rule in the |
214 // basic profile. They were already present in Orthanc 1.9.3. | 236 // basic profile. They were already present in Orthanc 1.9.3. |
215 RemoveIfEnabled(dicom, DICOM_TAG_REFERENCED_IMAGE_SEQUENCE); | 237 if (!IsManuallyModified(DICOM_TAG_REFERENCED_IMAGE_SEQUENCE)) |
216 RemoveIfEnabled(dicom, DICOM_TAG_SOURCE_IMAGE_SEQUENCE); | 238 { |
239 dicom.Remove(DICOM_TAG_REFERENCED_IMAGE_SEQUENCE); | |
240 } | |
241 | |
242 if (!IsManuallyModified(DICOM_TAG_SOURCE_IMAGE_SEQUENCE)) | |
243 { | |
244 dicom.Remove(DICOM_TAG_SOURCE_IMAGE_SEQUENCE); | |
245 } | |
217 } | 246 } |
218 }; | 247 }; |
219 | 248 |
220 | 249 |
221 bool DicomModification::CancelReplacement(const DicomTag& tag) | 250 bool DicomModification::CancelReplacement(const DicomTag& tag) |