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 }