comparison Core/DicomParsing/DicomModification.cpp @ 2382:7284093111b0

big reorganization to cleanly separate framework vs. server
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 29 Aug 2017 21:17:35 +0200
parents OrthancServer/DicomModification.cpp@f5fc61337bdf
children 878b59270859
comparison
equal deleted inserted replaced
2381:b8969010b534 2382:7284093111b0
1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017 Osimis, Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
11 *
12 * In addition, as a special exception, the copyright holders of this
13 * program give permission to link the code of its release with the
14 * OpenSSL project's "OpenSSL" library (or with modified versions of it
15 * that use the same license as the "OpenSSL" library), and distribute
16 * the linked executables. You must obey the GNU General Public License
17 * in all respects for all of the code used other than "OpenSSL". If you
18 * modify file(s) with this exception, you may extend this exception to
19 * your version of the file(s), but you are not obligated to do so. If
20 * you do not wish to do so, delete this exception statement from your
21 * version. If you delete this exception statement from all source files
22 * in the program, then also delete it here.
23 *
24 * This program is distributed in the hope that it will be useful, but
25 * WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31 **/
32
33
34 #include "../PrecompiledHeaders.h"
35 #include "DicomModification.h"
36
37 #include "../Logging.h"
38 #include "../OrthancException.h"
39 #include "FromDcmtkBridge.h"
40
41 #include <memory> // For std::auto_ptr
42
43
44 static const std::string ORTHANC_DEIDENTIFICATION_METHOD_2008 =
45 "Orthanc " ORTHANC_VERSION " - PS 3.15-2008 Table E.1-1";
46
47 static const std::string ORTHANC_DEIDENTIFICATION_METHOD_2017c =
48 "Orthanc " ORTHANC_VERSION " - PS 3.15-2017c Table E.1-1 Basic Profile";
49
50 namespace Orthanc
51 {
52 bool DicomModification::CancelReplacement(const DicomTag& tag)
53 {
54 Replacements::iterator it = replacements_.find(tag);
55
56 if (it != replacements_.end())
57 {
58 delete it->second;
59 replacements_.erase(it);
60 return true;
61 }
62 else
63 {
64 return false;
65 }
66 }
67
68
69 void DicomModification::ReplaceInternal(const DicomTag& tag,
70 const Json::Value& value)
71 {
72 Replacements::iterator it = replacements_.find(tag);
73
74 if (it != replacements_.end())
75 {
76 delete it->second;
77 it->second = NULL; // In the case of an exception during the clone
78 it->second = new Json::Value(value); // Clone
79 }
80 else
81 {
82 replacements_[tag] = new Json::Value(value); // Clone
83 }
84 }
85
86
87 void DicomModification::ClearReplacements()
88 {
89 for (Replacements::iterator it = replacements_.begin();
90 it != replacements_.end(); ++it)
91 {
92 delete it->second;
93 }
94
95 replacements_.clear();
96 }
97
98
99 void DicomModification::MarkNotOrthancAnonymization()
100 {
101 Replacements::iterator it = replacements_.find(DICOM_TAG_DEIDENTIFICATION_METHOD);
102
103 if (it != replacements_.end() &&
104 (it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2008 ||
105 it->second->asString() == ORTHANC_DEIDENTIFICATION_METHOD_2017c))
106 {
107 delete it->second;
108 replacements_.erase(it);
109 }
110 }
111
112
113 void DicomModification::MapDicomIdentifier(ParsedDicomFile& dicom,
114 ResourceType level)
115 {
116 std::auto_ptr<DicomTag> tag;
117
118 switch (level)
119 {
120 case ResourceType_Study:
121 tag.reset(new DicomTag(DICOM_TAG_STUDY_INSTANCE_UID));
122 break;
123
124 case ResourceType_Series:
125 tag.reset(new DicomTag(DICOM_TAG_SERIES_INSTANCE_UID));
126 break;
127
128 case ResourceType_Instance:
129 tag.reset(new DicomTag(DICOM_TAG_SOP_INSTANCE_UID));
130 break;
131
132 default:
133 throw OrthancException(ErrorCode_InternalError);
134 }
135
136 std::string original;
137 if (!dicom.GetTagValue(original, *tag))
138 {
139 original = "";
140 }
141
142 std::string mapped;
143
144 UidMap::const_iterator previous = uidMap_.find(std::make_pair(level, original));
145 if (previous == uidMap_.end())
146 {
147 mapped = FromDcmtkBridge::GenerateUniqueIdentifier(level);
148 uidMap_.insert(std::make_pair(std::make_pair(level, original), mapped));
149 }
150 else
151 {
152 mapped = previous->second;
153 }
154
155 dicom.Replace(*tag, mapped, false /* don't try and decode data URI scheme for UIDs */, DicomReplaceMode_InsertIfAbsent);
156 }
157
158 DicomModification::DicomModification() :
159 removePrivateTags_(false),
160 level_(ResourceType_Instance),
161 allowManualIdentifiers_(true),
162 keepStudyInstanceUid_(false),
163 keepSeriesInstanceUid_(false)
164 {
165 }
166
167 DicomModification::~DicomModification()
168 {
169 ClearReplacements();
170 }
171
172 void DicomModification::Keep(const DicomTag& tag)
173 {
174 bool wasRemoved = IsRemoved(tag);
175 bool wasCleared = IsCleared(tag);
176
177 removals_.erase(tag);
178 clearings_.erase(tag);
179
180 bool wasReplaced = CancelReplacement(tag);
181
182 if (tag == DICOM_TAG_STUDY_INSTANCE_UID)
183 {
184 keepStudyInstanceUid_ = true;
185 }
186 else if (tag == DICOM_TAG_SERIES_INSTANCE_UID)
187 {
188 keepSeriesInstanceUid_ = true;
189 }
190 else if (tag.IsPrivate())
191 {
192 privateTagsToKeep_.insert(tag);
193 }
194 else if (!wasRemoved &&
195 !wasReplaced &&
196 !wasCleared)
197 {
198 LOG(WARNING) << "Marking this tag as to be kept has no effect: " << tag.Format();
199 }
200
201 MarkNotOrthancAnonymization();
202 }
203
204 void DicomModification::Remove(const DicomTag& tag)
205 {
206 removals_.insert(tag);
207 clearings_.erase(tag);
208 CancelReplacement(tag);
209 privateTagsToKeep_.erase(tag);
210
211 MarkNotOrthancAnonymization();
212 }
213
214 void DicomModification::Clear(const DicomTag& tag)
215 {
216 removals_.erase(tag);
217 clearings_.insert(tag);
218 CancelReplacement(tag);
219 privateTagsToKeep_.erase(tag);
220
221 MarkNotOrthancAnonymization();
222 }
223
224 bool DicomModification::IsRemoved(const DicomTag& tag) const
225 {
226 return removals_.find(tag) != removals_.end();
227 }
228
229 bool DicomModification::IsCleared(const DicomTag& tag) const
230 {
231 return clearings_.find(tag) != clearings_.end();
232 }
233
234 void DicomModification::Replace(const DicomTag& tag,
235 const Json::Value& value,
236 bool safeForAnonymization)
237 {
238 clearings_.erase(tag);
239 removals_.erase(tag);
240 privateTagsToKeep_.erase(tag);
241 ReplaceInternal(tag, value);
242
243 if (!safeForAnonymization)
244 {
245 MarkNotOrthancAnonymization();
246 }
247 }
248
249
250 bool DicomModification::IsReplaced(const DicomTag& tag) const
251 {
252 return replacements_.find(tag) != replacements_.end();
253 }
254
255 const Json::Value& DicomModification::GetReplacement(const DicomTag& tag) const
256 {
257 Replacements::const_iterator it = replacements_.find(tag);
258
259 if (it == replacements_.end())
260 {
261 throw OrthancException(ErrorCode_InexistentItem);
262 }
263 else
264 {
265 return *it->second;
266 }
267 }
268
269
270 std::string DicomModification::GetReplacementAsString(const DicomTag& tag) const
271 {
272 const Json::Value& json = GetReplacement(tag);
273
274 if (json.type() != Json::stringValue)
275 {
276 throw OrthancException(ErrorCode_BadParameterType);
277 }
278 else
279 {
280 return json.asString();
281 }
282 }
283
284
285 void DicomModification::SetRemovePrivateTags(bool removed)
286 {
287 removePrivateTags_ = removed;
288
289 if (!removed)
290 {
291 MarkNotOrthancAnonymization();
292 }
293 }
294
295 void DicomModification::SetLevel(ResourceType level)
296 {
297 uidMap_.clear();
298 level_ = level;
299
300 if (level != ResourceType_Patient)
301 {
302 MarkNotOrthancAnonymization();
303 }
304 }
305
306
307 void DicomModification::SetupAnonymization2008()
308 {
309 // This is Table E.1-1 from PS 3.15-2008 - DICOM Part 15: Security and System Management Profiles
310 // https://raw.githubusercontent.com/jodogne/dicom-specification/master/2008/08_15pu.pdf
311
312 removals_.insert(DicomTag(0x0008, 0x0014)); // Instance Creator UID
313 //removals_.insert(DicomTag(0x0008, 0x0018)); // SOP Instance UID => set in Apply()
314 removals_.insert(DicomTag(0x0008, 0x0050)); // Accession Number
315 removals_.insert(DicomTag(0x0008, 0x0080)); // Institution Name
316 removals_.insert(DicomTag(0x0008, 0x0081)); // Institution Address
317 removals_.insert(DicomTag(0x0008, 0x0090)); // Referring Physician's Name
318 removals_.insert(DicomTag(0x0008, 0x0092)); // Referring Physician's Address
319 removals_.insert(DicomTag(0x0008, 0x0094)); // Referring Physician's Telephone Numbers
320 removals_.insert(DicomTag(0x0008, 0x1010)); // Station Name
321 removals_.insert(DicomTag(0x0008, 0x1030)); // Study Description
322 removals_.insert(DicomTag(0x0008, 0x103e)); // Series Description
323 removals_.insert(DicomTag(0x0008, 0x1040)); // Institutional Department Name
324 removals_.insert(DicomTag(0x0008, 0x1048)); // Physician(s) of Record
325 removals_.insert(DicomTag(0x0008, 0x1050)); // Performing Physicians' Name
326 removals_.insert(DicomTag(0x0008, 0x1060)); // Name of Physician(s) Reading Study
327 removals_.insert(DicomTag(0x0008, 0x1070)); // Operators' Name
328 removals_.insert(DicomTag(0x0008, 0x1080)); // Admitting Diagnoses Description
329 removals_.insert(DicomTag(0x0008, 0x1155)); // Referenced SOP Instance UID
330 removals_.insert(DicomTag(0x0008, 0x2111)); // Derivation Description
331 //removals_.insert(DicomTag(0x0010, 0x0010)); // Patient's Name => cf. below (*)
332 //removals_.insert(DicomTag(0x0010, 0x0020)); // Patient ID => cf. below (*)
333 removals_.insert(DicomTag(0x0010, 0x0030)); // Patient's Birth Date
334 removals_.insert(DicomTag(0x0010, 0x0032)); // Patient's Birth Time
335 removals_.insert(DicomTag(0x0010, 0x0040)); // Patient's Sex
336 removals_.insert(DicomTag(0x0010, 0x1000)); // Other Patient Ids
337 removals_.insert(DicomTag(0x0010, 0x1001)); // Other Patient Names
338 removals_.insert(DicomTag(0x0010, 0x1010)); // Patient's Age
339 removals_.insert(DicomTag(0x0010, 0x1020)); // Patient's Size
340 removals_.insert(DicomTag(0x0010, 0x1030)); // Patient's Weight
341 removals_.insert(DicomTag(0x0010, 0x1090)); // Medical Record Locator
342 removals_.insert(DicomTag(0x0010, 0x2160)); // Ethnic Group
343 removals_.insert(DicomTag(0x0010, 0x2180)); // Occupation
344 removals_.insert(DicomTag(0x0010, 0x21b0)); // Additional Patient's History
345 removals_.insert(DicomTag(0x0010, 0x4000)); // Patient Comments
346 removals_.insert(DicomTag(0x0018, 0x1000)); // Device Serial Number
347 removals_.insert(DicomTag(0x0018, 0x1030)); // Protocol Name
348 //removals_.insert(DicomTag(0x0020, 0x000d)); // Study Instance UID => set in Apply()
349 //removals_.insert(DicomTag(0x0020, 0x000e)); // Series Instance UID => set in Apply()
350 removals_.insert(DicomTag(0x0020, 0x0010)); // Study ID
351 removals_.insert(DicomTag(0x0020, 0x0052)); // Frame of Reference UID
352 removals_.insert(DicomTag(0x0020, 0x0200)); // Synchronization Frame of Reference UID
353 removals_.insert(DicomTag(0x0020, 0x4000)); // Image Comments
354 removals_.insert(DicomTag(0x0040, 0x0275)); // Request Attributes Sequence
355 removals_.insert(DicomTag(0x0040, 0xa124)); // UID
356 removals_.insert(DicomTag(0x0040, 0xa730)); // Content Sequence
357 removals_.insert(DicomTag(0x0088, 0x0140)); // Storage Media File-set UID
358 removals_.insert(DicomTag(0x3006, 0x0024)); // Referenced Frame of Reference UID
359 removals_.insert(DicomTag(0x3006, 0x00c2)); // Related Frame of Reference UID
360
361 // Some more removals (from the experience of DICOM files at the CHU of Liege)
362 removals_.insert(DicomTag(0x0010, 0x1040)); // Patient's Address
363 removals_.insert(DicomTag(0x0032, 0x1032)); // Requesting Physician
364 removals_.insert(DicomTag(0x0010, 0x2154)); // PatientTelephoneNumbers
365 removals_.insert(DicomTag(0x0010, 0x2000)); // Medical Alerts
366
367 // Set the DeidentificationMethod tag
368 ReplaceInternal(DICOM_TAG_DEIDENTIFICATION_METHOD, ORTHANC_DEIDENTIFICATION_METHOD_2008);
369 }
370
371
372 #if 0
373 /**
374 * This is a manual implementation by Alain Mazy. Only kept for reference.
375 * https://bitbucket.org/sjodogne/orthanc/commits/c6defdc4c611fca2ab528ba2c6937a742e0329a8?at=issue-46-anonymization
376 **/
377
378 void DicomModification::SetupAnonymization2011()
379 {
380 // This is Table E.1-1 from PS 3.15-2011 - DICOM Part 15: Security and System Management Profiles
381 // https://raw.githubusercontent.com/jodogne/dicom-specification/master/2011/11_15pu.pdf
382
383 removals_.insert(DicomTag(0x0000, 0x1000)); // Affected SOP Instance UID
384 removals_.insert(DicomTag(0x0000, 0x1001)); // Requested SOP Instance UID
385 removals_.insert(DicomTag(0x0002, 0x0003)); // Media Storage SOP Instance UID => TODO: replace with a non-zero length UID that is internally consistent within a set of Instances
386 removals_.insert(DicomTag(0x0004, 0x1511)); // Referenced SOP Instance UID in File
387 removals_.insert(DicomTag(0x0008, 0x0010)); // Irradiation Event UID
388 removals_.insert(DicomTag(0x0008, 0x0014)); // Instance Creator UID
389 //removals_.insert(DicomTag(0x0008, 0x0018)); // SOP Instance UID => set in Apply()
390 clearings_.insert(DicomTag(0x0008, 0x0020)); // Study Date
391 clearings_.insert(DicomTag(0x0008, 0x0021)); // Series Date
392 clearings_.insert(DicomTag(0x0008, 0x0030)); // Study Time
393 clearings_.insert(DicomTag(0x0008, 0x0031)); // Series Time
394 removals_.insert(DicomTag(0x0008, 0x0022)); // Acquisition Date
395 removals_.insert(DicomTag(0x0008, 0x0023)); // Content Date
396 removals_.insert(DicomTag(0x0008, 0x0024)); // Overlay Date
397 removals_.insert(DicomTag(0x0008, 0x0025)); // Curve Date
398 removals_.insert(DicomTag(0x0008, 0x002a)); // Acquisition DateTime
399 removals_.insert(DicomTag(0x0008, 0x0032)); // Acquisition Time
400 removals_.insert(DicomTag(0x0008, 0x0033)); // Content Time
401 removals_.insert(DicomTag(0x0008, 0x0034)); // Overlay Time
402 removals_.insert(DicomTag(0x0008, 0x0035)); // Curve Time
403 removals_.insert(DicomTag(0x0008, 0x0050)); // Accession Number
404 removals_.insert(DicomTag(0x0008, 0x0058)); // Failed SOP Instance UID List
405 removals_.insert(DicomTag(0x0008, 0x0080)); // Institution Name
406 removals_.insert(DicomTag(0x0008, 0x0081)); // Institution Address
407 removals_.insert(DicomTag(0x0008, 0x0082)); // Institution Code Sequence
408 removals_.insert(DicomTag(0x0008, 0x0090)); // Referring Physician's Name
409 removals_.insert(DicomTag(0x0008, 0x0092)); // Referring Physician's Address
410 removals_.insert(DicomTag(0x0008, 0x0094)); // Referring Physician's Telephone Numbers
411 removals_.insert(DicomTag(0x0008, 0x0096)); // Referring Physician's Identification Sequence
412 removals_.insert(DicomTag(0x0008, 0x010d)); // Context Group Extension Creator UID
413 removals_.insert(DicomTag(0x0008, 0x0201)); // Timezone Offset From UTC
414 removals_.insert(DicomTag(0x0008, 0x0300)); // Current Patient Location
415 removals_.insert(DicomTag(0x0008, 0x1010)); // Station Name
416 removals_.insert(DicomTag(0x0008, 0x1030)); // Study Description
417 removals_.insert(DicomTag(0x0008, 0x103e)); // Series Description
418 removals_.insert(DicomTag(0x0008, 0x1040)); // Institutional Department Name
419 removals_.insert(DicomTag(0x0008, 0x1048)); // Physician(s) of Record
420 removals_.insert(DicomTag(0x0008, 0x1049)); // Physician(s) of Record Identification Sequence
421 removals_.insert(DicomTag(0x0008, 0x1050)); // Performing Physicians' Name
422 removals_.insert(DicomTag(0x0008, 0x1052)); // Performing Physicians Identification Sequence
423 removals_.insert(DicomTag(0x0008, 0x1060)); // Name of Physician(s) Reading Study
424 removals_.insert(DicomTag(0x0008, 0x1062)); // Physician Reading Study Identification Sequence
425 removals_.insert(DicomTag(0x0008, 0x1070)); // Operators' Name
426 removals_.insert(DicomTag(0x0008, 0x1072)); // Operators' Identification Sequence
427 removals_.insert(DicomTag(0x0008, 0x1080)); // Admitting Diagnoses Description
428 removals_.insert(DicomTag(0x0008, 0x1084)); // Admitting Diagnoses Code Sequence
429 removals_.insert(DicomTag(0x0008, 0x1110)); // Referenced Study Sequence
430 removals_.insert(DicomTag(0x0008, 0x1111)); // Referenced Performed Procedure Step Sequence
431 removals_.insert(DicomTag(0x0008, 0x1120)); // Referenced Patient Sequence
432 removals_.insert(DicomTag(0x0008, 0x1140)); // Referenced Image Sequence
433 removals_.insert(DicomTag(0x0008, 0x1155)); // Referenced SOP Instance UID
434 removals_.insert(DicomTag(0x0008, 0x1195)); // Transaction UID
435 removals_.insert(DicomTag(0x0008, 0x2111)); // Derivation Description
436 removals_.insert(DicomTag(0x0008, 0x2112)); // Source Image Sequence
437 removals_.insert(DicomTag(0x0008, 0x4000)); // Identifying Comments
438 removals_.insert(DicomTag(0x0008, 0x9123)); // Creator Version UID
439 //removals_.insert(DicomTag(0x0010, 0x0010)); // Patient's Name => cf. below (*)
440 //removals_.insert(DicomTag(0x0010, 0x0020)); // Patient ID => cf. below (*)
441 removals_.insert(DicomTag(0x0010, 0x0030)); // Patient's Birth Date
442 removals_.insert(DicomTag(0x0010, 0x0032)); // Patient's Birth Time
443 clearings_.insert(DicomTag(0x0010, 0x0040)); // Patient's Sex
444 removals_.insert(DicomTag(0x0010, 0x0050)); // Patient's Insurance Plan Code Sequence
445 removals_.insert(DicomTag(0x0010, 0x0101)); // Patient's Primary Language Code Sequence
446 removals_.insert(DicomTag(0x0010, 0x0102)); // Patient's Primary Language Modifier Code Sequence
447 removals_.insert(DicomTag(0x0010, 0x1000)); // Other Patient Ids
448 removals_.insert(DicomTag(0x0010, 0x1001)); // Other Patient Names
449 removals_.insert(DicomTag(0x0010, 0x1002)); // Other Patient IDs Sequence
450 removals_.insert(DicomTag(0x0010, 0x1005)); // Patient's Birth Name
451 removals_.insert(DicomTag(0x0010, 0x1010)); // Patient's Age
452 removals_.insert(DicomTag(0x0010, 0x1020)); // Patient's Size
453 removals_.insert(DicomTag(0x0010, 0x1030)); // Patient's Weight
454 removals_.insert(DicomTag(0x0010, 0x1040)); // Patient's Address
455 removals_.insert(DicomTag(0x0010, 0x1050)); // Insurance Plan Identification
456 removals_.insert(DicomTag(0x0010, 0x1060)); // Patient's Mother's Birth Name
457 removals_.insert(DicomTag(0x0010, 0x1080)); // Military Rank
458 removals_.insert(DicomTag(0x0010, 0x1081)); // Branch of Service
459 removals_.insert(DicomTag(0x0010, 0x1090)); // Medical Record Locator
460 removals_.insert(DicomTag(0x0010, 0x2000)); // Medical Alerts
461 removals_.insert(DicomTag(0x0010, 0x2110)); // Allergies
462 removals_.insert(DicomTag(0x0010, 0x2150)); // Country of Residence
463 removals_.insert(DicomTag(0x0010, 0x2152)); // Region of Residence
464 removals_.insert(DicomTag(0x0010, 0x2154)); // PatientTelephoneNumbers
465 removals_.insert(DicomTag(0x0010, 0x2160)); // Ethnic Group
466 removals_.insert(DicomTag(0x0010, 0x2180)); // Occupation
467 removals_.insert(DicomTag(0x0010, 0x21a0)); // Smoking Status
468 removals_.insert(DicomTag(0x0010, 0x21b0)); // Additional Patient's History
469 removals_.insert(DicomTag(0x0010, 0x21c0)); // Pregnancy Status
470 removals_.insert(DicomTag(0x0010, 0x21d0)); // Last Menstrual Date
471 removals_.insert(DicomTag(0x0010, 0x21f0)); // Patient's Religious Preference
472 removals_.insert(DicomTag(0x0010, 0x2203)); // Patient's Sex Neutered
473 removals_.insert(DicomTag(0x0010, 0x2297)); // Responsible Person
474 removals_.insert(DicomTag(0x0010, 0x2299)); // Responsible Organization
475 removals_.insert(DicomTag(0x0010, 0x4000)); // Patient Comments
476 removals_.insert(DicomTag(0x0018, 0x0010)); // Contrast Bolus Agent
477 removals_.insert(DicomTag(0x0018, 0x1000)); // Device Serial Number
478 removals_.insert(DicomTag(0x0018, 0x1002)); // Device UID
479 removals_.insert(DicomTag(0x0018, 0x1004)); // Plate ID
480 removals_.insert(DicomTag(0x0018, 0x1005)); // Generator ID
481 removals_.insert(DicomTag(0x0018, 0x1007)); // Cassette ID
482 removals_.insert(DicomTag(0x0018, 0x1008)); // Gantry ID
483 removals_.insert(DicomTag(0x0018, 0x1030)); // Protocol Name
484 removals_.insert(DicomTag(0x0018, 0x1400)); // Acquisition Device Processing Description
485 removals_.insert(DicomTag(0x0018, 0x4000)); // Acquisition Comments
486 removals_.insert(DicomTag(0x0018, 0x700a)); // Detector ID
487 removals_.insert(DicomTag(0x0018, 0xa003)); // Contribution Description
488 removals_.insert(DicomTag(0x0018, 0x9424)); // Acquisition Protocol Description
489 //removals_.insert(DicomTag(0x0020, 0x000d)); // Study Instance UID => set in Apply()
490 //removals_.insert(DicomTag(0x0020, 0x000e)); // Series Instance UID => set in Apply()
491 removals_.insert(DicomTag(0x0020, 0x0010)); // Study ID
492 removals_.insert(DicomTag(0x0020, 0x0052)); // Frame of Reference UID
493 removals_.insert(DicomTag(0x0020, 0x0200)); // Synchronization Frame of Reference UID
494 removals_.insert(DicomTag(0x0020, 0x3401)); // Modifying Device ID
495 removals_.insert(DicomTag(0x0020, 0x3404)); // Modifying Device Manufacturer
496 removals_.insert(DicomTag(0x0020, 0x3406)); // Modified Image Description
497 removals_.insert(DicomTag(0x0020, 0x4000)); // Image Comments
498 removals_.insert(DicomTag(0x0020, 0x9158)); // Frame Comments
499 removals_.insert(DicomTag(0x0020, 0x9161)); // Concatenation UID
500 removals_.insert(DicomTag(0x0020, 0x9164)); // Dimension Organization UID
501 //removals_.insert(DicomTag(0x0028, 0x1199)); // Palette Color Lookup Table UID => TODO: replace with a non-zero length UID that is internally consistent within a set of Instances
502 //removals_.insert(DicomTag(0x0028, 0x1214)); // Large Palette Color Lookup Table UID => TODO: replace with a non-zero length UID that is internally consistent within a set of Instances
503 removals_.insert(DicomTag(0x0028, 0x4000)); // Image Presentation Comments
504 removals_.insert(DicomTag(0x0032, 0x0012)); // Study ID Issuer
505 removals_.insert(DicomTag(0x0032, 0x1020)); // Scheduled Study Location
506 removals_.insert(DicomTag(0x0032, 0x1021)); // Scheduled Study Location AE Title
507 removals_.insert(DicomTag(0x0032, 0x1030)); // Reason for Study
508 removals_.insert(DicomTag(0x0032, 0x1032)); // Requesting Physician
509 removals_.insert(DicomTag(0x0032, 0x1033)); // Requesting Service
510 removals_.insert(DicomTag(0x0032, 0x1060)); // Requesting Procedure Description
511 removals_.insert(DicomTag(0x0032, 0x1070)); // Requested Contrast Agent
512 removals_.insert(DicomTag(0x0032, 0x4000)); // Study Comments
513 removals_.insert(DicomTag(0x0038, 0x0010)); // Admission ID
514 removals_.insert(DicomTag(0x0038, 0x0011)); // Issuer of Admission ID
515 removals_.insert(DicomTag(0x0038, 0x001e)); // Scheduled Patient Institution Residence
516 removals_.insert(DicomTag(0x0038, 0x0020)); // Admitting Date
517 removals_.insert(DicomTag(0x0038, 0x0021)); // Admitting Time
518 removals_.insert(DicomTag(0x0038, 0x0040)); // Discharge Diagnosis Description
519 removals_.insert(DicomTag(0x0038, 0x0050)); // Special Needs
520 removals_.insert(DicomTag(0x0038, 0x0060)); // Service Episode ID
521 removals_.insert(DicomTag(0x0038, 0x0061)); // Issuer of Service Episode ID
522 removals_.insert(DicomTag(0x0038, 0x0062)); // Service Episode Description
523 removals_.insert(DicomTag(0x0038, 0x0400)); // Patient's Institution Residence
524 removals_.insert(DicomTag(0x0038, 0x0500)); // Patient State
525 removals_.insert(DicomTag(0x0038, 0x4000)); // Visit Comments
526 removals_.insert(DicomTag(0x0038, 0x1234)); // Referenced Patient Alias Sequence
527 removals_.insert(DicomTag(0x0040, 0x0001)); // Scheduled Station AE Title
528 removals_.insert(DicomTag(0x0040, 0x0002)); // Scheduled Procedure Step Start Date
529 removals_.insert(DicomTag(0x0040, 0x0003)); // Scheduled Procedure Step Start Time
530 removals_.insert(DicomTag(0x0040, 0x0004)); // Scheduled Procedure Step End Date
531 removals_.insert(DicomTag(0x0040, 0x0005)); // Scheduled Procedure Step End Time
532 removals_.insert(DicomTag(0x0040, 0x0006)); // Scheduled Performing Physician Name
533 removals_.insert(DicomTag(0x0040, 0x0007)); // Scheduled Procedure Step Description
534 removals_.insert(DicomTag(0x0040, 0x000b)); // Scheduled Performing Physician Identification Sequence
535 removals_.insert(DicomTag(0x0040, 0x0010)); // Scheduled Station Name
536 removals_.insert(DicomTag(0x0040, 0x0011)); // Scheduled Procedure Step Location
537 removals_.insert(DicomTag(0x0040, 0x0012)); // Pre-Medication
538 removals_.insert(DicomTag(0x0040, 0x0241)); // Performed Station AE Title
539 removals_.insert(DicomTag(0x0040, 0x0242)); // Performed Station Name
540 removals_.insert(DicomTag(0x0040, 0x0243)); // Performed Location
541 removals_.insert(DicomTag(0x0040, 0x0244)); // Performed Procedure Step Start Date
542 removals_.insert(DicomTag(0x0040, 0x0245)); // Performed Procedure Step Start Time
543 removals_.insert(DicomTag(0x0040, 0x0248)); // Performed Station Name Code Sequence
544 removals_.insert(DicomTag(0x0040, 0x0253)); // Performed Procedure Step ID
545 removals_.insert(DicomTag(0x0040, 0x0254)); // Performed Procedure Step Description
546 removals_.insert(DicomTag(0x0040, 0x0275)); // Request Attributes Sequence
547 removals_.insert(DicomTag(0x0040, 0x0280)); // Comments on Performed Procedure Step
548 removals_.insert(DicomTag(0x0040, 0x0555)); // Acquisition Context Sequence
549 removals_.insert(DicomTag(0x0040, 0x1001)); // Requested Procedure ID
550 removals_.insert(DicomTag(0x0040, 0x1010)); // Names of Intended Recipient of Results
551 removals_.insert(DicomTag(0x0040, 0x1011)); // Intended Recipient of Results Identification Sequence
552 removals_.insert(DicomTag(0x0040, 0x1004)); // Patient Transport Arrangements
553 removals_.insert(DicomTag(0x0040, 0x1005)); // Requested Procedure Location
554 removals_.insert(DicomTag(0x0040, 0x1101)); // Person Identification Code Sequence
555 removals_.insert(DicomTag(0x0040, 0x1102)); // Person Address
556 removals_.insert(DicomTag(0x0040, 0x1103)); // Person Telephone Numbers
557 removals_.insert(DicomTag(0x0040, 0x1400)); // Requested Procedure Comments
558 removals_.insert(DicomTag(0x0040, 0x2001)); // Reason for Imaging Service Request
559 removals_.insert(DicomTag(0x0040, 0x2008)); // Order Entered By
560 removals_.insert(DicomTag(0x0040, 0x2009)); // Order Enterer Location
561 removals_.insert(DicomTag(0x0040, 0x2010)); // Order Callback Phone Number
562 removals_.insert(DicomTag(0x0040, 0x2016)); // Placer Order Number of Imaging Service Request
563 removals_.insert(DicomTag(0x0040, 0x2017)); // Filler Order Number of Imaging Service Request
564 removals_.insert(DicomTag(0x0040, 0x2400)); // Imaging Service Request Comments
565 removals_.insert(DicomTag(0x0040, 0x4023)); // Referenced General Purpose Scheduled Procedure Step Transaction UID
566 removals_.insert(DicomTag(0x0040, 0x4025)); // Scheduled Station Name Code Sequence
567 removals_.insert(DicomTag(0x0040, 0x4027)); // Scheduled Station Geographic Location Code Sequence
568 removals_.insert(DicomTag(0x0040, 0x4030)); // Performed Station Geographic Location Code Sequence
569 removals_.insert(DicomTag(0x0040, 0x4034)); // Scheduled Human Performers Sequence
570 removals_.insert(DicomTag(0x0040, 0x4035)); // Actual Human Performers Sequence
571 removals_.insert(DicomTag(0x0040, 0x4036)); // Human Performers Organization
572 removals_.insert(DicomTag(0x0040, 0x4037)); // Human Performers Name
573 removals_.insert(DicomTag(0x0040, 0xa027)); // Verifying Organization
574 removals_.insert(DicomTag(0x0040, 0xa073)); // Verifying Observer Sequence
575 removals_.insert(DicomTag(0x0040, 0xa075)); // Verifying Observer Name
576 removals_.insert(DicomTag(0x0040, 0xa078)); // Author Observer Sequence
577 removals_.insert(DicomTag(0x0040, 0xa07a)); // Participant Sequence
578 removals_.insert(DicomTag(0x0040, 0xa07c)); // Custodial Organization Sequence
579 removals_.insert(DicomTag(0x0040, 0xa088)); // Verifying Observer Identification Code Sequence
580 removals_.insert(DicomTag(0x0040, 0xa123)); // Person Name
581 removals_.insert(DicomTag(0x0040, 0xa124)); // UID
582 removals_.insert(DicomTag(0x0040, 0xa730)); // Content Sequence
583 removals_.insert(DicomTag(0x0040, 0x3001)); // Confidentiality Constraint on Patient Data Description
584 removals_.insert(DicomTag(0x0040, 0xdb0c)); // Template Extension Organization UID
585 removals_.insert(DicomTag(0x0040, 0xdb0d)); // Template Extension Creator UID
586 removals_.insert(DicomTag(0x0070, 0x0001)); // Graphic Annotation Sequence
587 removals_.insert(DicomTag(0x0070, 0x0084)); // Content Creator's Name
588 removals_.insert(DicomTag(0x0070, 0x0086)); // Content Creator's Identification Code Sequence
589 removals_.insert(DicomTag(0x0070, 0x031a)); // Fiducial UID
590 removals_.insert(DicomTag(0x0088, 0x0140)); // Storage Media File-set UID
591 removals_.insert(DicomTag(0x0088, 0x0200)); // Icon Image Sequence
592 removals_.insert(DicomTag(0x0088, 0x0904)); // Topic Title
593 removals_.insert(DicomTag(0x0088, 0x0906)); // Topic Subject
594 removals_.insert(DicomTag(0x0088, 0x0910)); // Topic Author
595 removals_.insert(DicomTag(0x0088, 0x0912)); // Topic Key Words
596 removals_.insert(DicomTag(0x0400, 0x0100)); // Digital Signature UID
597 removals_.insert(DicomTag(0x0400, 0x0402)); // Referenced Digital Signature Sequence
598 removals_.insert(DicomTag(0x0400, 0x0403)); // Referenced SOP Instance MAC Sequence
599 removals_.insert(DicomTag(0x0400, 0x0404)); // MAC
600 removals_.insert(DicomTag(0x0400, 0x0550)); // Modified Attributes Sequence
601 removals_.insert(DicomTag(0x0400, 0x0561)); // Original Attributes Sequence
602 removals_.insert(DicomTag(0x2030, 0x0020)); // Text String
603 removals_.insert(DicomTag(0x3006, 0x0024)); // Referenced Frame of Reference UID
604 removals_.insert(DicomTag(0x3006, 0x00c2)); // Related Frame of Reference UID
605 removals_.insert(DicomTag(0x300a, 0x0013)); // Dose Reference UID
606 removals_.insert(DicomTag(0x300e, 0x0008)); // Reviewer Name
607 removals_.insert(DicomTag(0x4000, 0x0010)); // Arbitrary
608 removals_.insert(DicomTag(0x4000, 0x4000)); // Text Comments
609 removals_.insert(DicomTag(0x4008, 0x0042)); // Results ID Issuer
610 removals_.insert(DicomTag(0x4008, 0x0102)); // Interpretation Recorder
611 removals_.insert(DicomTag(0x4008, 0x010a)); // Interpretation Transcriber
612 removals_.insert(DicomTag(0x4008, 0x010b)); // Interpretation Text
613 removals_.insert(DicomTag(0x4008, 0x010c)); // Interpretation Author
614 removals_.insert(DicomTag(0x4008, 0x0111)); // Interpretation Approver Sequence
615 removals_.insert(DicomTag(0x4008, 0x0114)); // Physician Approving Interpretation
616 removals_.insert(DicomTag(0x4008, 0x0115)); // Interpretation Diagnosis Description
617 removals_.insert(DicomTag(0x4008, 0x0118)); // Results Distribution List Sequence
618 removals_.insert(DicomTag(0x4008, 0x0119)); // Distribution Name
619 removals_.insert(DicomTag(0x4008, 0x011a)); // Distribution Address
620 removals_.insert(DicomTag(0x4008, 0x0202)); // Interpretation ID Issuer
621 removals_.insert(DicomTag(0x4008, 0x0300)); // Impressions
622 removals_.insert(DicomTag(0x4008, 0x4000)); // Results Comments
623 removals_.insert(DicomTag(0xfffa, 0xfffa)); // Digital Signature Sequence
624 removals_.insert(DicomTag(0xfffc, 0xfffc)); // Data Set Trailing Padding
625 //removals_.insert(DicomTag(0x60xx, 0x4000)); // Overlay Comments => TODO
626 //removals_.insert(DicomTag(0x60xx, 0x3000)); // Overlay Data => TODO
627
628 // Set the DeidentificationMethod tag
629 ReplaceInternal(DICOM_TAG_DEIDENTIFICATION_METHOD, ORTHANC_DEIDENTIFICATION_METHOD_2011);
630 }
631 #endif
632
633
634
635 void DicomModification::SetupAnonymization2017c()
636 {
637 /**
638 * This is Table E.1-1 from PS 3.15-2017c (DICOM Part 15: Security
639 * and System Management Profiles), "basic profile" column. It was
640 * generated automatically with the
641 * "../Resources/GenerateAnonymizationProfile.py" script.
642 * https://raw.githubusercontent.com/jodogne/dicom-specification/master/2017c/part15.pdf
643 **/
644
645 // TODO: (50xx,xxxx) with rule X // Curve Data
646 // TODO: (60xx,3000) with rule X // Overlay Data
647 // TODO: (60xx,4000) with rule X // Overlay Comments
648 // Tag (0x0008, 0x0018) is set in Apply() // SOP Instance UID
649 // Tag (0x0010, 0x0010) is set below (*) // Patient's Name
650 // Tag (0x0010, 0x0020) is set below (*) // Patient ID
651 // Tag (0x0020, 0x000d) is set in Apply() // Study Instance UID
652 // Tag (0x0020, 0x000e) is set in Apply() // Series Instance UID
653 clearings_.insert(DicomTag(0x0008, 0x0020)); // Study Date
654 clearings_.insert(DicomTag(0x0008, 0x0023)); /* Z/D */ // Content Date
655 clearings_.insert(DicomTag(0x0008, 0x0030)); // Study Time
656 clearings_.insert(DicomTag(0x0008, 0x0033)); /* Z/D */ // Content Time
657 clearings_.insert(DicomTag(0x0008, 0x0050)); // Accession Number
658 clearings_.insert(DicomTag(0x0008, 0x0090)); // Referring Physician's Name
659 clearings_.insert(DicomTag(0x0008, 0x009c)); // Consulting Physician's Name
660 clearings_.insert(DicomTag(0x0010, 0x0030)); // Patient's Birth Date
661 clearings_.insert(DicomTag(0x0010, 0x0040)); // Patient's Sex
662 clearings_.insert(DicomTag(0x0018, 0x0010)); /* Z/D */ // Contrast Bolus Agent
663 clearings_.insert(DicomTag(0x0020, 0x0010)); // Study ID
664 clearings_.insert(DicomTag(0x0040, 0x1101)); /* D */ // Person Identification Code Sequence
665 clearings_.insert(DicomTag(0x0040, 0x2016)); // Placer Order Number / Imaging Service Request
666 clearings_.insert(DicomTag(0x0040, 0x2017)); // Filler Order Number / Imaging Service Request
667 clearings_.insert(DicomTag(0x0040, 0xa073)); /* D */ // Verifying Observer Sequence
668 clearings_.insert(DicomTag(0x0040, 0xa075)); /* D */ // Verifying Observer Name
669 clearings_.insert(DicomTag(0x0040, 0xa088)); // Verifying Observer Identification Code Sequence
670 clearings_.insert(DicomTag(0x0040, 0xa123)); /* D */ // Person Name
671 clearings_.insert(DicomTag(0x0070, 0x0001)); /* D */ // Graphic Annotation Sequence
672 clearings_.insert(DicomTag(0x0070, 0x0084)); // Content Creator's Name
673 removals_.insert(DicomTag(0x0000, 0x1000)); // Affected SOP Instance UID
674 removals_.insert(DicomTag(0x0000, 0x1001)); /* TODO UID */ // Requested SOP Instance UID
675 removals_.insert(DicomTag(0x0002, 0x0003)); /* TODO UID */ // Media Storage SOP Instance UID
676 removals_.insert(DicomTag(0x0004, 0x1511)); /* TODO UID */ // Referenced SOP Instance UID in File
677 removals_.insert(DicomTag(0x0008, 0x0014)); /* TODO UID */ // Instance Creator UID
678 removals_.insert(DicomTag(0x0008, 0x0015)); // Instance Coercion DateTime
679 removals_.insert(DicomTag(0x0008, 0x0021)); /* X/D */ // Series Date
680 removals_.insert(DicomTag(0x0008, 0x0022)); /* X/Z */ // Acquisition Date
681 removals_.insert(DicomTag(0x0008, 0x0024)); // Overlay Date
682 removals_.insert(DicomTag(0x0008, 0x0025)); // Curve Date
683 removals_.insert(DicomTag(0x0008, 0x002a)); /* X/D */ // Acquisition DateTime
684 removals_.insert(DicomTag(0x0008, 0x0031)); /* X/D */ // Series Time
685 removals_.insert(DicomTag(0x0008, 0x0032)); /* X/Z */ // Acquisition Time
686 removals_.insert(DicomTag(0x0008, 0x0034)); // Overlay Time
687 removals_.insert(DicomTag(0x0008, 0x0035)); // Curve Time
688 removals_.insert(DicomTag(0x0008, 0x0058)); /* TODO UID */ // Failed SOP Instance UID List
689 removals_.insert(DicomTag(0x0008, 0x0080)); /* X/Z/D */ // Institution Name
690 removals_.insert(DicomTag(0x0008, 0x0081)); // Institution Address
691 removals_.insert(DicomTag(0x0008, 0x0082)); /* X/Z/D */ // Institution Code Sequence
692 removals_.insert(DicomTag(0x0008, 0x0092)); // Referring Physician's Address
693 removals_.insert(DicomTag(0x0008, 0x0094)); // Referring Physician's Telephone Numbers
694 removals_.insert(DicomTag(0x0008, 0x0096)); // Referring Physician Identification Sequence
695 removals_.insert(DicomTag(0x0008, 0x009d)); // Consulting Physician Identification Sequence
696 removals_.insert(DicomTag(0x0008, 0x0201)); // Timezone Offset From UTC
697 removals_.insert(DicomTag(0x0008, 0x1010)); /* X/Z/D */ // Station Name
698 removals_.insert(DicomTag(0x0008, 0x1030)); // Study Description
699 removals_.insert(DicomTag(0x0008, 0x103e)); // Series Description
700 removals_.insert(DicomTag(0x0008, 0x1040)); // Institutional Department Name
701 removals_.insert(DicomTag(0x0008, 0x1048)); // Physician(s) of Record
702 removals_.insert(DicomTag(0x0008, 0x1049)); // Physician(s) of Record Identification Sequence
703 removals_.insert(DicomTag(0x0008, 0x1050)); // Performing Physicians' Name
704 removals_.insert(DicomTag(0x0008, 0x1052)); // Performing Physician Identification Sequence
705 removals_.insert(DicomTag(0x0008, 0x1060)); // Name of Physician(s) Reading Study
706 removals_.insert(DicomTag(0x0008, 0x1062)); // Physician(s) Reading Study Identification Sequence
707 removals_.insert(DicomTag(0x0008, 0x1070)); /* X/Z/D */ // Operators' Name
708 removals_.insert(DicomTag(0x0008, 0x1072)); /* X/D */ // Operators' Identification Sequence
709 removals_.insert(DicomTag(0x0008, 0x1080)); // Admitting Diagnoses Description
710 removals_.insert(DicomTag(0x0008, 0x1084)); // Admitting Diagnoses Code Sequence
711 removals_.insert(DicomTag(0x0008, 0x1110)); /* X/Z */ // Referenced Study Sequence
712 removals_.insert(DicomTag(0x0008, 0x1111)); /* X/Z/D */ // Referenced Performed Procedure Step Sequence
713 removals_.insert(DicomTag(0x0008, 0x1120)); // Referenced Patient Sequence
714 removals_.insert(DicomTag(0x0008, 0x1140)); /* X/Z/U* */ // Referenced Image Sequence
715 removals_.insert(DicomTag(0x0008, 0x1155)); /* TODO UID */ // Referenced SOP Instance UID
716 removals_.insert(DicomTag(0x0008, 0x1195)); /* TODO UID */ // Transaction UID
717 removals_.insert(DicomTag(0x0008, 0x2111)); // Derivation Description
718 removals_.insert(DicomTag(0x0008, 0x2112)); /* X/Z/U* */ // Source Image Sequence
719 removals_.insert(DicomTag(0x0008, 0x3010)); /* TODO UID */ // Irradiation Event UID
720 removals_.insert(DicomTag(0x0008, 0x4000)); // Identifying Comments
721 removals_.insert(DicomTag(0x0010, 0x0021)); // Issuer of Patient ID
722 removals_.insert(DicomTag(0x0010, 0x0032)); // Patient's Birth Time
723 removals_.insert(DicomTag(0x0010, 0x0050)); // Patient's Insurance Plan Code Sequence
724 removals_.insert(DicomTag(0x0010, 0x0101)); // Patient's Primary Language Code Sequence
725 removals_.insert(DicomTag(0x0010, 0x0102)); // Patient's Primary Language Modifier Code Sequence
726 removals_.insert(DicomTag(0x0010, 0x1000)); // Other Patient IDs
727 removals_.insert(DicomTag(0x0010, 0x1001)); // Other Patient Names
728 removals_.insert(DicomTag(0x0010, 0x1002)); // Other Patient IDs Sequence
729 removals_.insert(DicomTag(0x0010, 0x1005)); // Patient's Birth Name
730 removals_.insert(DicomTag(0x0010, 0x1010)); // Patient's Age
731 removals_.insert(DicomTag(0x0010, 0x1020)); // Patient's Size
732 removals_.insert(DicomTag(0x0010, 0x1030)); // Patient's Weight
733 removals_.insert(DicomTag(0x0010, 0x1040)); // Patient Address
734 removals_.insert(DicomTag(0x0010, 0x1050)); // Insurance Plan Identification
735 removals_.insert(DicomTag(0x0010, 0x1060)); // Patient's Mother's Birth Name
736 removals_.insert(DicomTag(0x0010, 0x1080)); // Military Rank
737 removals_.insert(DicomTag(0x0010, 0x1081)); // Branch of Service
738 removals_.insert(DicomTag(0x0010, 0x1090)); // Medical Record Locator
739 removals_.insert(DicomTag(0x0010, 0x1100)); // Referenced Patient Photo Sequence
740 removals_.insert(DicomTag(0x0010, 0x2000)); // Medical Alerts
741 removals_.insert(DicomTag(0x0010, 0x2110)); // Allergies
742 removals_.insert(DicomTag(0x0010, 0x2150)); // Country of Residence
743 removals_.insert(DicomTag(0x0010, 0x2152)); // Region of Residence
744 removals_.insert(DicomTag(0x0010, 0x2154)); // Patient's Telephone Numbers
745 removals_.insert(DicomTag(0x0010, 0x2155)); // Patient's Telecom Information
746 removals_.insert(DicomTag(0x0010, 0x2160)); // Ethnic Group
747 removals_.insert(DicomTag(0x0010, 0x2180)); // Occupation
748 removals_.insert(DicomTag(0x0010, 0x21a0)); // Smoking Status
749 removals_.insert(DicomTag(0x0010, 0x21b0)); // Additional Patient's History
750 removals_.insert(DicomTag(0x0010, 0x21c0)); // Pregnancy Status
751 removals_.insert(DicomTag(0x0010, 0x21d0)); // Last Menstrual Date
752 removals_.insert(DicomTag(0x0010, 0x21f0)); // Patient's Religious Preference
753 removals_.insert(DicomTag(0x0010, 0x2203)); /* X/Z */ // Patient Sex Neutered
754 removals_.insert(DicomTag(0x0010, 0x2297)); // Responsible Person
755 removals_.insert(DicomTag(0x0010, 0x2299)); // Responsible Organization
756 removals_.insert(DicomTag(0x0010, 0x4000)); // Patient Comments
757 removals_.insert(DicomTag(0x0018, 0x1000)); /* X/Z/D */ // Device Serial Number
758 removals_.insert(DicomTag(0x0018, 0x1002)); /* TODO UID */ // Device UID
759 removals_.insert(DicomTag(0x0018, 0x1004)); // Plate ID
760 removals_.insert(DicomTag(0x0018, 0x1005)); // Generator ID
761 removals_.insert(DicomTag(0x0018, 0x1007)); // Cassette ID
762 removals_.insert(DicomTag(0x0018, 0x1008)); // Gantry ID
763 removals_.insert(DicomTag(0x0018, 0x1030)); /* X/D */ // Protocol Name
764 removals_.insert(DicomTag(0x0018, 0x1400)); /* X/D */ // Acquisition Device Processing Description
765 removals_.insert(DicomTag(0x0018, 0x2042)); /* TODO UID */ // Target UID
766 removals_.insert(DicomTag(0x0018, 0x4000)); // Acquisition Comments
767 removals_.insert(DicomTag(0x0018, 0x700a)); /* X/D */ // Detector ID
768 removals_.insert(DicomTag(0x0018, 0x9424)); // Acquisition Protocol Description
769 removals_.insert(DicomTag(0x0018, 0x9516)); /* X/D */ // Start Acquisition DateTime
770 removals_.insert(DicomTag(0x0018, 0x9517)); /* X/D */ // End Acquisition DateTime
771 removals_.insert(DicomTag(0x0018, 0xa003)); // Contribution Description
772 removals_.insert(DicomTag(0x0020, 0x0052)); /* TODO UID */ // Frame of Reference UID
773 removals_.insert(DicomTag(0x0020, 0x0200)); /* TODO UID */ // Synchronization Frame of Reference UID
774 removals_.insert(DicomTag(0x0020, 0x3401)); // Modifying Device ID
775 removals_.insert(DicomTag(0x0020, 0x3404)); // Modifying Device Manufacturer
776 removals_.insert(DicomTag(0x0020, 0x3406)); // Modified Image Description
777 removals_.insert(DicomTag(0x0020, 0x4000)); // Image Comments
778 removals_.insert(DicomTag(0x0020, 0x9158)); // Frame Comments
779 removals_.insert(DicomTag(0x0020, 0x9161)); /* TODO UID */ // Concatenation UID
780 removals_.insert(DicomTag(0x0020, 0x9164)); /* TODO UID */ // Dimension Organization UID
781 removals_.insert(DicomTag(0x0028, 0x1199)); /* TODO UID */ // Palette Color Lookup Table UID
782 removals_.insert(DicomTag(0x0028, 0x1214)); /* TODO UID */ // Large Palette Color Lookup Table UID
783 removals_.insert(DicomTag(0x0028, 0x4000)); // Image Presentation Comments
784 removals_.insert(DicomTag(0x0032, 0x0012)); // Study ID Issuer
785 removals_.insert(DicomTag(0x0032, 0x1020)); // Scheduled Study Location
786 removals_.insert(DicomTag(0x0032, 0x1021)); // Scheduled Study Location AE Title
787 removals_.insert(DicomTag(0x0032, 0x1030)); // Reason for Study
788 removals_.insert(DicomTag(0x0032, 0x1032)); // Requesting Physician
789 removals_.insert(DicomTag(0x0032, 0x1033)); // Requesting Service
790 removals_.insert(DicomTag(0x0032, 0x1060)); /* X/Z */ // Requested Procedure Description
791 removals_.insert(DicomTag(0x0032, 0x1070)); // Requested Contrast Agent
792 removals_.insert(DicomTag(0x0032, 0x4000)); // Study Comments
793 removals_.insert(DicomTag(0x0038, 0x0004)); // Referenced Patient Alias Sequence
794 removals_.insert(DicomTag(0x0038, 0x0010)); // Admission ID
795 removals_.insert(DicomTag(0x0038, 0x0011)); // Issuer of Admission ID
796 removals_.insert(DicomTag(0x0038, 0x001e)); // Scheduled Patient Institution Residence
797 removals_.insert(DicomTag(0x0038, 0x0020)); // Admitting Date
798 removals_.insert(DicomTag(0x0038, 0x0021)); // Admitting Time
799 removals_.insert(DicomTag(0x0038, 0x0040)); // Discharge Diagnosis Description
800 removals_.insert(DicomTag(0x0038, 0x0050)); // Special Needs
801 removals_.insert(DicomTag(0x0038, 0x0060)); // Service Episode ID
802 removals_.insert(DicomTag(0x0038, 0x0061)); // Issuer of Service Episode ID
803 removals_.insert(DicomTag(0x0038, 0x0062)); // Service Episode Description
804 removals_.insert(DicomTag(0x0038, 0x0300)); // Current Patient Location
805 removals_.insert(DicomTag(0x0038, 0x0400)); // Patient's Institution Residence
806 removals_.insert(DicomTag(0x0038, 0x0500)); // Patient State
807 removals_.insert(DicomTag(0x0038, 0x4000)); // Visit Comments
808 removals_.insert(DicomTag(0x0040, 0x0001)); // Scheduled Station AE Title
809 removals_.insert(DicomTag(0x0040, 0x0002)); // Scheduled Procedure Step Start Date
810 removals_.insert(DicomTag(0x0040, 0x0003)); // Scheduled Procedure Step Start Time
811 removals_.insert(DicomTag(0x0040, 0x0004)); // Scheduled Procedure Step End Date
812 removals_.insert(DicomTag(0x0040, 0x0005)); // Scheduled Procedure Step End Time
813 removals_.insert(DicomTag(0x0040, 0x0006)); // Scheduled Performing Physician Name
814 removals_.insert(DicomTag(0x0040, 0x0007)); // Scheduled Procedure Step Description
815 removals_.insert(DicomTag(0x0040, 0x000b)); // Scheduled Performing Physician Identification Sequence
816 removals_.insert(DicomTag(0x0040, 0x0010)); // Scheduled Station Name
817 removals_.insert(DicomTag(0x0040, 0x0011)); // Scheduled Procedure Step Location
818 removals_.insert(DicomTag(0x0040, 0x0012)); // Pre-Medication
819 removals_.insert(DicomTag(0x0040, 0x0241)); // Performed Station AE Title
820 removals_.insert(DicomTag(0x0040, 0x0242)); // Performed Station Name
821 removals_.insert(DicomTag(0x0040, 0x0243)); // Performed Location
822 removals_.insert(DicomTag(0x0040, 0x0244)); // Performed Procedure Step Start Date
823 removals_.insert(DicomTag(0x0040, 0x0245)); // Performed Procedure Step Start Time
824 removals_.insert(DicomTag(0x0040, 0x0250)); // Performed Procedure Step End Date
825 removals_.insert(DicomTag(0x0040, 0x0251)); // Performed Procedure Step End Time
826 removals_.insert(DicomTag(0x0040, 0x0253)); // Performed Procedure Step ID
827 removals_.insert(DicomTag(0x0040, 0x0254)); // Performed Procedure Step Description
828 removals_.insert(DicomTag(0x0040, 0x0275)); // Request Attributes Sequence
829 removals_.insert(DicomTag(0x0040, 0x0280)); // Comments on the Performed Procedure Step
830 removals_.insert(DicomTag(0x0040, 0x0555)); // Acquisition Context Sequence
831 removals_.insert(DicomTag(0x0040, 0x1001)); // Requested Procedure ID
832 removals_.insert(DicomTag(0x0040, 0x1004)); // Patient Transport Arrangements
833 removals_.insert(DicomTag(0x0040, 0x1005)); // Requested Procedure Location
834 removals_.insert(DicomTag(0x0040, 0x1010)); // Names of Intended Recipient of Results
835 removals_.insert(DicomTag(0x0040, 0x1011)); // Intended Recipients of Results Identification Sequence
836 removals_.insert(DicomTag(0x0040, 0x1102)); // Person Address
837 removals_.insert(DicomTag(0x0040, 0x1103)); // Person's Telephone Numbers
838 removals_.insert(DicomTag(0x0040, 0x1104)); // Person's Telecom Information
839 removals_.insert(DicomTag(0x0040, 0x1400)); // Requested Procedure Comments
840 removals_.insert(DicomTag(0x0040, 0x2001)); // Reason for the Imaging Service Request
841 removals_.insert(DicomTag(0x0040, 0x2008)); // Order Entered By
842 removals_.insert(DicomTag(0x0040, 0x2009)); // Order Enterer Location
843 removals_.insert(DicomTag(0x0040, 0x2010)); // Order Callback Phone Number
844 removals_.insert(DicomTag(0x0040, 0x2011)); // Order Callback Telecom Information
845 removals_.insert(DicomTag(0x0040, 0x2400)); // Imaging Service Request Comments
846 removals_.insert(DicomTag(0x0040, 0x3001)); // Confidentiality Constraint on Patient Data Description
847 removals_.insert(DicomTag(0x0040, 0x4005)); // Scheduled Procedure Step Start DateTime
848 removals_.insert(DicomTag(0x0040, 0x4010)); // Scheduled Procedure Step Modification DateTime
849 removals_.insert(DicomTag(0x0040, 0x4011)); // Expected Completion DateTime
850 removals_.insert(DicomTag(0x0040, 0x4023)); /* TODO UID */ // Referenced General Purpose Scheduled Procedure Step Transaction UID
851 removals_.insert(DicomTag(0x0040, 0x4025)); // Scheduled Station Name Code Sequence
852 removals_.insert(DicomTag(0x0040, 0x4027)); // Scheduled Station Geographic Location Code Sequence
853 removals_.insert(DicomTag(0x0040, 0x4028)); // Performed Station Name Code Sequence
854 removals_.insert(DicomTag(0x0040, 0x4030)); // Performed Station Geographic Location Code Sequence
855 removals_.insert(DicomTag(0x0040, 0x4034)); // Scheduled Human Performers Sequence
856 removals_.insert(DicomTag(0x0040, 0x4035)); // Actual Human Performers Sequence
857 removals_.insert(DicomTag(0x0040, 0x4036)); // Human Performers Organization
858 removals_.insert(DicomTag(0x0040, 0x4037)); // Human Performers Name
859 removals_.insert(DicomTag(0x0040, 0x4050)); // Performed Procedure Step Start DateTime
860 removals_.insert(DicomTag(0x0040, 0x4051)); // Performed Procedure Step End DateTime
861 removals_.insert(DicomTag(0x0040, 0x4052)); // Procedure Step Cancellation DateTime
862 removals_.insert(DicomTag(0x0040, 0xa027)); // Verifying Organization
863 removals_.insert(DicomTag(0x0040, 0xa078)); // Author Observer Sequence
864 removals_.insert(DicomTag(0x0040, 0xa07a)); // Participant Sequence
865 removals_.insert(DicomTag(0x0040, 0xa07c)); // Custodial Organization Sequence
866 removals_.insert(DicomTag(0x0040, 0xa124)); /* TODO UID */ // UID
867 removals_.insert(DicomTag(0x0040, 0xa171)); /* TODO UID */ // Observation UID
868 removals_.insert(DicomTag(0x0040, 0xa172)); /* TODO UID */ // Referenced Observation UID (Trial)
869 removals_.insert(DicomTag(0x0040, 0xa192)); // Observation Date (Trial)
870 removals_.insert(DicomTag(0x0040, 0xa193)); // Observation Time (Trial)
871 removals_.insert(DicomTag(0x0040, 0xa307)); // Current Observer (Trial)
872 removals_.insert(DicomTag(0x0040, 0xa352)); // Verbal Source (Trial)
873 removals_.insert(DicomTag(0x0040, 0xa353)); // Address (Trial)
874 removals_.insert(DicomTag(0x0040, 0xa354)); // Telephone Number (Trial)
875 removals_.insert(DicomTag(0x0040, 0xa358)); // Verbal Source Identifier Code Sequence (Trial)
876 removals_.insert(DicomTag(0x0040, 0xa402)); /* TODO UID */ // Observation Subject UID (Trial)
877 removals_.insert(DicomTag(0x0040, 0xa730)); // Content Sequence
878 removals_.insert(DicomTag(0x0040, 0xdb0c)); /* TODO UID */ // Template Extension Organization UID
879 removals_.insert(DicomTag(0x0040, 0xdb0d)); /* TODO UID */ // Template Extension Creator UID
880 removals_.insert(DicomTag(0x0062, 0x0021)); /* TODO UID */ // Tracking UID
881 removals_.insert(DicomTag(0x0070, 0x0086)); // Content Creator's Identification Code Sequence
882 removals_.insert(DicomTag(0x0070, 0x031a)); /* TODO UID */ // Fiducial UID
883 removals_.insert(DicomTag(0x0070, 0x1101)); /* TODO UID */ // Presentation Display Collection UID
884 removals_.insert(DicomTag(0x0070, 0x1102)); /* TODO UID */ // Presentation Sequence Collection UID
885 removals_.insert(DicomTag(0x0088, 0x0140)); /* TODO UID */ // Storage Media File-set UID
886 removals_.insert(DicomTag(0x0088, 0x0200)); // Icon Image Sequence(see Note 12)
887 removals_.insert(DicomTag(0x0088, 0x0904)); // Topic Title
888 removals_.insert(DicomTag(0x0088, 0x0906)); // Topic Subject
889 removals_.insert(DicomTag(0x0088, 0x0910)); // Topic Author
890 removals_.insert(DicomTag(0x0088, 0x0912)); // Topic Keywords
891 removals_.insert(DicomTag(0x0400, 0x0100)); // Digital Signature UID
892 removals_.insert(DicomTag(0x0400, 0x0402)); // Referenced Digital Signature Sequence
893 removals_.insert(DicomTag(0x0400, 0x0403)); // Referenced SOP Instance MAC Sequence
894 removals_.insert(DicomTag(0x0400, 0x0404)); // MAC
895 removals_.insert(DicomTag(0x0400, 0x0550)); // Modified Attributes Sequence
896 removals_.insert(DicomTag(0x0400, 0x0561)); // Original Attributes Sequence
897 removals_.insert(DicomTag(0x2030, 0x0020)); // Text String
898 removals_.insert(DicomTag(0x3006, 0x0024)); /* TODO UID */ // Referenced Frame of Reference UID
899 removals_.insert(DicomTag(0x3006, 0x00c2)); /* TODO UID */ // Related Frame of Reference UID
900 removals_.insert(DicomTag(0x3008, 0x0105)); // Source Serial Number
901 removals_.insert(DicomTag(0x300a, 0x0013)); /* TODO UID */ // Dose Reference UID
902 removals_.insert(DicomTag(0x300c, 0x0113)); // Reason for Omission Description
903 removals_.insert(DicomTag(0x300e, 0x0008)); /* X/Z */ // Reviewer Name
904 removals_.insert(DicomTag(0x4000, 0x0010)); // Arbitrary
905 removals_.insert(DicomTag(0x4000, 0x4000)); // Text Comments
906 removals_.insert(DicomTag(0x4008, 0x0042)); // Results ID Issuer
907 removals_.insert(DicomTag(0x4008, 0x0102)); // Interpretation Recorder
908 removals_.insert(DicomTag(0x4008, 0x010a)); // Interpretation Transcriber
909 removals_.insert(DicomTag(0x4008, 0x010b)); // Interpretation Text
910 removals_.insert(DicomTag(0x4008, 0x010c)); // Interpretation Author
911 removals_.insert(DicomTag(0x4008, 0x0111)); // Interpretation Approver Sequence
912 removals_.insert(DicomTag(0x4008, 0x0114)); // Physician Approving Interpretation
913 removals_.insert(DicomTag(0x4008, 0x0115)); // Interpretation Diagnosis Description
914 removals_.insert(DicomTag(0x4008, 0x0118)); // Results Distribution List Sequence
915 removals_.insert(DicomTag(0x4008, 0x0119)); // Distribution Name
916 removals_.insert(DicomTag(0x4008, 0x011a)); // Distribution Address
917 removals_.insert(DicomTag(0x4008, 0x0202)); // Interpretation ID Issuer
918 removals_.insert(DicomTag(0x4008, 0x0300)); // Impressions
919 removals_.insert(DicomTag(0x4008, 0x4000)); // Results Comments
920 removals_.insert(DicomTag(0xfffa, 0xfffa)); // Digital Signatures Sequence
921 removals_.insert(DicomTag(0xfffc, 0xfffc)); // Data Set Trailing Padding
922
923 // Set the DeidentificationMethod tag
924 ReplaceInternal(DICOM_TAG_DEIDENTIFICATION_METHOD, ORTHANC_DEIDENTIFICATION_METHOD_2017c);
925 }
926
927
928 void DicomModification::SetupAnonymization(DicomVersion version)
929 {
930 removals_.clear();
931 clearings_.clear();
932 ClearReplacements();
933 removePrivateTags_ = true;
934 level_ = ResourceType_Patient;
935 uidMap_.clear();
936 privateTagsToKeep_.clear();
937
938 switch (version)
939 {
940 case DicomVersion_2008:
941 SetupAnonymization2008();
942 break;
943
944 case DicomVersion_2017c:
945 SetupAnonymization2017c();
946 break;
947
948 default:
949 throw OrthancException(ErrorCode_ParameterOutOfRange);
950 }
951
952 // Set the PatientIdentityRemoved tag
953 ReplaceInternal(DicomTag(0x0012, 0x0062), "YES");
954
955 // (*) Choose a random patient name and ID
956 std::string patientId = FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Patient);
957 ReplaceInternal(DICOM_TAG_PATIENT_ID, patientId);
958 ReplaceInternal(DICOM_TAG_PATIENT_NAME, patientId);
959 }
960
961 void DicomModification::Apply(ParsedDicomFile& toModify)
962 {
963 // Check the request
964 assert(ResourceType_Patient + 1 == ResourceType_Study &&
965 ResourceType_Study + 1 == ResourceType_Series &&
966 ResourceType_Series + 1 == ResourceType_Instance);
967
968 if (IsRemoved(DICOM_TAG_PATIENT_ID) ||
969 IsRemoved(DICOM_TAG_STUDY_INSTANCE_UID) ||
970 IsRemoved(DICOM_TAG_SERIES_INSTANCE_UID) ||
971 IsRemoved(DICOM_TAG_SOP_INSTANCE_UID))
972 {
973 throw OrthancException(ErrorCode_BadRequest);
974 }
975
976
977 // Sanity checks at the patient level
978 if (level_ == ResourceType_Patient && !IsReplaced(DICOM_TAG_PATIENT_ID))
979 {
980 LOG(ERROR) << "When modifying a patient, her PatientID is required to be modified";
981 throw OrthancException(ErrorCode_BadRequest);
982 }
983
984 if (!allowManualIdentifiers_)
985 {
986 if (level_ == ResourceType_Patient && IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID))
987 {
988 LOG(ERROR) << "When modifying a patient, the StudyInstanceUID cannot be manually modified";
989 throw OrthancException(ErrorCode_BadRequest);
990 }
991
992 if (level_ == ResourceType_Patient && IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID))
993 {
994 LOG(ERROR) << "When modifying a patient, the SeriesInstanceUID cannot be manually modified";
995 throw OrthancException(ErrorCode_BadRequest);
996 }
997
998 if (level_ == ResourceType_Patient && IsReplaced(DICOM_TAG_SOP_INSTANCE_UID))
999 {
1000 LOG(ERROR) << "When modifying a patient, the SopInstanceUID cannot be manually modified";
1001 throw OrthancException(ErrorCode_BadRequest);
1002 }
1003 }
1004
1005
1006 // Sanity checks at the study level
1007 if (level_ == ResourceType_Study && IsReplaced(DICOM_TAG_PATIENT_ID))
1008 {
1009 LOG(ERROR) << "When modifying a study, the parent PatientID cannot be manually modified";
1010 throw OrthancException(ErrorCode_BadRequest);
1011 }
1012
1013 if (!allowManualIdentifiers_)
1014 {
1015 if (level_ == ResourceType_Study && IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID))
1016 {
1017 LOG(ERROR) << "When modifying a study, the SeriesInstanceUID cannot be manually modified";
1018 throw OrthancException(ErrorCode_BadRequest);
1019 }
1020
1021 if (level_ == ResourceType_Study && IsReplaced(DICOM_TAG_SOP_INSTANCE_UID))
1022 {
1023 LOG(ERROR) << "When modifying a study, the SopInstanceUID cannot be manually modified";
1024 throw OrthancException(ErrorCode_BadRequest);
1025 }
1026 }
1027
1028
1029 // Sanity checks at the series level
1030 if (level_ == ResourceType_Series && IsReplaced(DICOM_TAG_PATIENT_ID))
1031 {
1032 LOG(ERROR) << "When modifying a series, the parent PatientID cannot be manually modified";
1033 throw OrthancException(ErrorCode_BadRequest);
1034 }
1035
1036 if (level_ == ResourceType_Series && IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID))
1037 {
1038 LOG(ERROR) << "When modifying a series, the parent StudyInstanceUID cannot be manually modified";
1039 throw OrthancException(ErrorCode_BadRequest);
1040 }
1041
1042 if (!allowManualIdentifiers_)
1043 {
1044 if (level_ == ResourceType_Series && IsReplaced(DICOM_TAG_SOP_INSTANCE_UID))
1045 {
1046 LOG(ERROR) << "When modifying a series, the SopInstanceUID cannot be manually modified";
1047 throw OrthancException(ErrorCode_BadRequest);
1048 }
1049 }
1050
1051
1052 // Sanity checks at the instance level
1053 if (level_ == ResourceType_Instance && IsReplaced(DICOM_TAG_PATIENT_ID))
1054 {
1055 LOG(ERROR) << "When modifying an instance, the parent PatientID cannot be manually modified";
1056 throw OrthancException(ErrorCode_BadRequest);
1057 }
1058
1059 if (level_ == ResourceType_Instance && IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID))
1060 {
1061 LOG(ERROR) << "When modifying an instance, the parent StudyInstanceUID cannot be manually modified";
1062 throw OrthancException(ErrorCode_BadRequest);
1063 }
1064
1065 if (level_ == ResourceType_Instance && IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID))
1066 {
1067 LOG(ERROR) << "When modifying an instance, the parent SeriesInstanceUID cannot be manually modified";
1068 throw OrthancException(ErrorCode_BadRequest);
1069 }
1070
1071
1072 // (1) Remove the private tags, if need be
1073 if (removePrivateTags_)
1074 {
1075 toModify.RemovePrivateTags(privateTagsToKeep_);
1076 }
1077
1078 // (2) Clear the tags specified by the user
1079 for (SetOfTags::const_iterator it = clearings_.begin();
1080 it != clearings_.end(); ++it)
1081 {
1082 toModify.Clear(*it, true /* only clear if the tag exists in the original file */);
1083 }
1084
1085 // (3) Remove the tags specified by the user
1086 for (SetOfTags::const_iterator it = removals_.begin();
1087 it != removals_.end(); ++it)
1088 {
1089 toModify.Remove(*it);
1090 }
1091
1092 // (4) Replace the tags
1093 for (Replacements::const_iterator it = replacements_.begin();
1094 it != replacements_.end(); ++it)
1095 {
1096 toModify.Replace(it->first, *it->second, true /* decode data URI scheme */, DicomReplaceMode_InsertIfAbsent);
1097 }
1098
1099 // (5) Update the DICOM identifiers
1100 if (level_ <= ResourceType_Study &&
1101 !IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID))
1102 {
1103 if (keepStudyInstanceUid_)
1104 {
1105 LOG(WARNING) << "Modifying a study while keeping its original StudyInstanceUID: This should be avoided!";
1106 }
1107 else
1108 {
1109 MapDicomIdentifier(toModify, ResourceType_Study);
1110 }
1111 }
1112
1113 if (level_ <= ResourceType_Series &&
1114 !IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID))
1115 {
1116 if (keepSeriesInstanceUid_)
1117 {
1118 LOG(WARNING) << "Modifying a series while keeping its original SeriesInstanceUID: This should be avoided!";
1119 }
1120 else
1121 {
1122 MapDicomIdentifier(toModify, ResourceType_Series);
1123 }
1124 }
1125
1126 if (level_ <= ResourceType_Instance && // Always true
1127 !IsReplaced(DICOM_TAG_SOP_INSTANCE_UID))
1128 {
1129 MapDicomIdentifier(toModify, ResourceType_Instance);
1130 }
1131 }
1132 }