Mercurial > hg > orthanc
comparison 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 |
comparison
equal
deleted
inserted
replaced
4684:e3810750dc9d | 4685:693f049729ba |
---|---|
167 } | 167 } |
168 } | 168 } |
169 else | 169 else |
170 { | 170 { |
171 // We are within a sequence | 171 // We are within a sequence |
172 | |
173 if (!that_.keepSequences_.empty()) | |
174 { | |
175 // New in Orthanc 1.9.4 - Solves issue LSD-629 | |
176 DicomPath path(parentTags, parentIndexes, tag); | |
177 | |
178 for (ListOfPaths::const_iterator it = that_.keepSequences_.begin(); | |
179 it != that_.keepSequences_.end(); ++it) | |
180 { | |
181 if (DicomPath::IsMatch(*it, path)) | |
182 { | |
183 return Action_None; | |
184 } | |
185 } | |
186 } | |
187 | |
172 if (tag == DICOM_TAG_STUDY_INSTANCE_UID) | 188 if (tag == DICOM_TAG_STUDY_INSTANCE_UID) |
173 { | 189 { |
174 newValue = that_.MapDicomIdentifier(value, ResourceType_Study); | 190 newValue = that_.MapDicomIdentifier(value, ResourceType_Study); |
175 return Action_Replace; | 191 return Action_Replace; |
176 } | 192 } |
245 } | 261 } |
246 } | 262 } |
247 }; | 263 }; |
248 | 264 |
249 | 265 |
250 bool DicomModification::CancelReplacement(const DicomTag& tag) | 266 void DicomModification::CancelReplacement(const DicomTag& tag) |
251 { | 267 { |
252 Replacements::iterator it = replacements_.find(tag); | 268 Replacements::iterator it = replacements_.find(tag); |
253 | 269 |
254 if (it != replacements_.end()) | 270 if (it != replacements_.end()) |
255 { | 271 { |
272 assert(it->second != NULL); | |
256 delete it->second; | 273 delete it->second; |
257 replacements_.erase(it); | 274 replacements_.erase(it); |
258 return true; | |
259 } | |
260 else | |
261 { | |
262 return false; | |
263 } | 275 } |
264 } | 276 } |
265 | 277 |
266 | 278 |
267 void DicomModification::ReplaceInternal(const DicomTag& tag, | 279 void DicomModification::ReplaceInternal(const DicomTag& tag, |
269 { | 281 { |
270 Replacements::iterator it = replacements_.find(tag); | 282 Replacements::iterator it = replacements_.find(tag); |
271 | 283 |
272 if (it != replacements_.end()) | 284 if (it != replacements_.end()) |
273 { | 285 { |
286 assert(it->second != NULL); | |
274 delete it->second; | 287 delete it->second; |
275 it->second = NULL; // In the case of an exception during the clone | 288 it->second = NULL; // In the case of an exception during the clone |
276 it->second = new Json::Value(value); // Clone | 289 it->second = new Json::Value(value); // Clone |
277 } | 290 } |
278 else | 291 else |
285 void DicomModification::ClearReplacements() | 298 void DicomModification::ClearReplacements() |
286 { | 299 { |
287 for (Replacements::iterator it = replacements_.begin(); | 300 for (Replacements::iterator it = replacements_.begin(); |
288 it != replacements_.end(); ++it) | 301 it != replacements_.end(); ++it) |
289 { | 302 { |
303 assert(it->second != NULL); | |
290 delete it->second; | 304 delete it->second; |
291 } | 305 } |
292 | 306 |
293 replacements_.clear(); | 307 replacements_.clear(); |
308 | |
309 for (SequenceReplacements::iterator it = sequenceReplacements_.begin(); | |
310 it != sequenceReplacements_.end(); ++it) | |
311 { | |
312 assert(*it != NULL); | |
313 assert((*it)->GetPath().GetPrefixLength() > 0); | |
314 delete *it; | |
315 } | |
316 | |
317 sequenceReplacements_.clear(); | |
294 } | 318 } |
295 | 319 |
296 | 320 |
297 void DicomModification::MarkNotOrthancAnonymization() | 321 void DicomModification::MarkNotOrthancAnonymization() |
298 { | 322 { |
299 Replacements::iterator it = replacements_.find(DICOM_TAG_DEIDENTIFICATION_METHOD); | 323 Replacements::iterator it = replacements_.find(DICOM_TAG_DEIDENTIFICATION_METHOD); |
300 | 324 |
301 if (it != replacements_.end() && | 325 if (it != replacements_.end()) |
302 (it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2008 || | 326 { |
303 it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2017c || | 327 assert(it->second != NULL); |
304 it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2021b)) | 328 |
305 { | 329 if (it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2008 || |
306 delete it->second; | 330 it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2017c || |
307 replacements_.erase(it); | 331 it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2021b) |
332 { | |
333 delete it->second; | |
334 replacements_.erase(it); | |
335 } | |
308 } | 336 } |
309 } | 337 } |
310 | 338 |
311 void DicomModification::RegisterMappedDicomIdentifier(const std::string& original, | 339 void DicomModification::RegisterMappedDicomIdentifier(const std::string& original, |
312 const std::string& mapped, | 340 const std::string& mapped, |
411 ClearReplacements(); | 439 ClearReplacements(); |
412 } | 440 } |
413 | 441 |
414 void DicomModification::Keep(const DicomTag& tag) | 442 void DicomModification::Keep(const DicomTag& tag) |
415 { | 443 { |
416 bool wasRemoved = IsRemoved(tag); | |
417 bool wasCleared = IsCleared(tag); | |
418 | |
419 removals_.erase(tag); | 444 removals_.erase(tag); |
420 clearings_.erase(tag); | 445 clearings_.erase(tag); |
421 uids_.erase(tag); | 446 uids_.erase(tag); |
422 | 447 |
423 bool wasReplaced = CancelReplacement(tag); | 448 CancelReplacement(tag); |
424 | 449 |
425 if (tag == DICOM_TAG_STUDY_INSTANCE_UID) | 450 if (tag == DICOM_TAG_STUDY_INSTANCE_UID) |
426 { | 451 { |
427 keepStudyInstanceUid_ = true; | 452 keepStudyInstanceUid_ = true; |
428 } | 453 } |
435 keepSopInstanceUid_ = true; | 460 keepSopInstanceUid_ = true; |
436 } | 461 } |
437 else if (tag.IsPrivate()) | 462 else if (tag.IsPrivate()) |
438 { | 463 { |
439 privateTagsToKeep_.insert(tag); | 464 privateTagsToKeep_.insert(tag); |
440 } | |
441 else if (!wasRemoved && | |
442 !wasReplaced && | |
443 !wasCleared) | |
444 { | |
445 LOG(WARNING) << "Marking this tag as to be kept has no effect: " << tag.Format(); | |
446 } | 465 } |
447 | 466 |
448 MarkNotOrthancAnonymization(); | 467 MarkNotOrthancAnonymization(); |
449 } | 468 } |
450 | 469 |
526 { | 545 { |
527 throw OrthancException(ErrorCode_InexistentItem); | 546 throw OrthancException(ErrorCode_InexistentItem); |
528 } | 547 } |
529 else | 548 else |
530 { | 549 { |
550 assert(it->second != NULL); | |
531 return *it->second; | 551 return *it->second; |
532 } | 552 } |
533 } | 553 } |
534 | 554 |
535 | 555 |
725 ClearReplacements(); | 745 ClearReplacements(); |
726 removePrivateTags_ = true; | 746 removePrivateTags_ = true; |
727 level_ = ResourceType_Patient; | 747 level_ = ResourceType_Patient; |
728 uidMap_.clear(); | 748 uidMap_.clear(); |
729 privateTagsToKeep_.clear(); | 749 privateTagsToKeep_.clear(); |
750 keepSequences_.clear(); | |
751 removeSequences_.clear(); | |
730 | 752 |
731 switch (version) | 753 switch (version) |
732 { | 754 { |
733 case DicomVersion_2008: | 755 case DicomVersion_2008: |
734 SetupAnonymization2008(); | 756 SetupAnonymization2008(); |
935 | 957 |
936 // (5) Replace the tags | 958 // (5) Replace the tags |
937 for (Replacements::const_iterator it = replacements_.begin(); | 959 for (Replacements::const_iterator it = replacements_.begin(); |
938 it != replacements_.end(); ++it) | 960 it != replacements_.end(); ++it) |
939 { | 961 { |
962 assert(it->second != NULL); | |
940 toModify.Replace(it->first, *it->second, true /* decode data URI scheme */, | 963 toModify.Replace(it->first, *it->second, true /* decode data URI scheme */, |
941 DicomReplaceMode_InsertIfAbsent, privateCreator_); | 964 DicomReplaceMode_InsertIfAbsent, privateCreator_); |
942 } | 965 } |
943 | 966 |
944 // (6) Update the DICOM identifiers | 967 // (6) New in Orthanc 1.9.4: Apply modifications to subsequences |
968 for (ListOfPaths::const_iterator it = removeSequences_.begin(); | |
969 it != removeSequences_.end(); ++it) | |
970 { | |
971 assert(it->GetPrefixLength() > 0); | |
972 toModify.RemovePath(*it); | |
973 } | |
974 | |
975 for (SequenceReplacements::const_iterator it = sequenceReplacements_.begin(); | |
976 it != sequenceReplacements_.end(); ++it) | |
977 { | |
978 assert(*it != NULL); | |
979 assert((*it)->GetPath().GetPrefixLength() > 0); | |
980 toModify.ReplacePath((*it)->GetPath(), (*it)->GetValue(), true /* decode data URI scheme */, | |
981 DicomReplaceMode_InsertIfAbsent, privateCreator_); | |
982 } | |
983 | |
984 // (7) Update the DICOM identifiers | |
945 if (level_ <= ResourceType_Study && | 985 if (level_ <= ResourceType_Study && |
946 !IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID)) | 986 !IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID)) |
947 { | 987 { |
948 if (keepStudyInstanceUid_) | 988 if (keepStudyInstanceUid_) |
949 { | 989 { |
979 { | 1019 { |
980 MapDicomTags(toModify, ResourceType_Instance); | 1020 MapDicomTags(toModify, ResourceType_Instance); |
981 } | 1021 } |
982 } | 1022 } |
983 | 1023 |
984 // (7) Update the "referenced" relationships in the case of an anonymization | 1024 // (8) Update the "referenced" relationships in the case of an anonymization |
985 if (isAnonymization_) | 1025 if (isAnonymization_) |
986 { | 1026 { |
987 RelationshipsVisitor visitor(*this); | 1027 RelationshipsVisitor visitor(*this); |
988 | 1028 |
989 if (updateReferencedRelationships_) | 1029 if (updateReferencedRelationships_) |
1087 throw OrthancException(ErrorCode_BadRequest, | 1127 throw OrthancException(ErrorCode_BadRequest, |
1088 "Marking tag \"" + name + "\" as to be replaced " + | 1128 "Marking tag \"" + name + "\" as to be replaced " + |
1089 "requires the \"Force\" option to be set to true"); | 1129 "requires the \"Force\" option to be set to true"); |
1090 } | 1130 } |
1091 | 1131 |
1092 target.Replace(tag, value, false); | 1132 target.Replace(tag, value, false /* not safe for anonymization */); |
1093 | 1133 |
1094 LOG(TRACE) << "Replace: " << name << " (" << tag.Format() | 1134 LOG(TRACE) << "Replace: " << name << " (" << tag.Format() |
1095 << ") == " << value.toStyledString(); | 1135 << ") == " << value.toStyledString(); |
1096 } | 1136 } |
1097 } | 1137 } |
1481 | 1521 |
1482 const std::string &DicomModification::GetPrivateCreator() const | 1522 const std::string &DicomModification::GetPrivateCreator() const |
1483 { | 1523 { |
1484 return privateCreator_; | 1524 return privateCreator_; |
1485 } | 1525 } |
1526 | |
1527 | |
1528 void DicomModification::Keep(const DicomPath& path) | |
1529 { | |
1530 if (path.GetPrefixLength() == 0) | |
1531 { | |
1532 Keep(path.GetFinalTag()); | |
1533 } | |
1534 | |
1535 keepSequences_.push_back(path); | |
1536 MarkNotOrthancAnonymization(); | |
1537 } | |
1538 | |
1539 | |
1540 void DicomModification::Remove(const DicomPath& path) | |
1541 { | |
1542 if (path.GetPrefixLength() == 0) | |
1543 { | |
1544 Remove(path.GetFinalTag()); | |
1545 } | |
1546 else | |
1547 { | |
1548 removeSequences_.push_back(path); | |
1549 MarkNotOrthancAnonymization(); | |
1550 } | |
1551 } | |
1552 | |
1553 | |
1554 void DicomModification::Replace(const DicomPath& path, | |
1555 const Json::Value& value, | |
1556 bool safeForAnonymization) | |
1557 { | |
1558 if (path.GetPrefixLength() == 0) | |
1559 { | |
1560 Replace(path.GetFinalTag(), value, safeForAnonymization); | |
1561 } | |
1562 else | |
1563 { | |
1564 sequenceReplacements_.push_back(new SequenceReplacement(path, value)); | |
1565 | |
1566 if (!safeForAnonymization) | |
1567 { | |
1568 MarkNotOrthancAnonymization(); | |
1569 } | |
1570 } | |
1571 } | |
1486 } | 1572 } |