Mercurial > hg > orthanc
comparison OrthancServer/DicomModification.cpp @ 1279:7f3a65e84d4b
More flexible /modify and /anonymize for single instance
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 02 Feb 2015 16:14:29 +0100 |
parents | 80671157d051 |
children | 6e7e5ed91c2d |
comparison
equal
deleted
inserted
replaced
1278:7aa0630a958e | 1279:7f3a65e84d4b |
---|---|
37 #include "FromDcmtkBridge.h" | 37 #include "FromDcmtkBridge.h" |
38 | 38 |
39 #include <memory> // For std::auto_ptr | 39 #include <memory> // For std::auto_ptr |
40 #include <glog/logging.h> | 40 #include <glog/logging.h> |
41 | 41 |
42 | |
43 static const std::string ORTHANC_DEIDENTIFICATION_METHOD = "Orthanc " ORTHANC_VERSION " - PS 3.15-2008 Table E.1-1"; | |
44 | |
42 namespace Orthanc | 45 namespace Orthanc |
43 { | 46 { |
47 void DicomModification::MarkNotOrthancAnonymization() | |
48 { | |
49 Replacements::iterator it = replacements_.find(DICOM_TAG_DEIDENTIFICATION_METHOD); | |
50 | |
51 if (it != replacements_.end() && | |
52 it->second == ORTHANC_DEIDENTIFICATION_METHOD) | |
53 { | |
54 replacements_.erase(it); | |
55 } | |
56 } | |
57 | |
58 | |
44 void DicomModification::MapDicomIdentifier(ParsedDicomFile& dicom, | 59 void DicomModification::MapDicomIdentifier(ParsedDicomFile& dicom, |
45 ResourceType level) | 60 ResourceType level) |
46 { | 61 { |
47 std::auto_ptr<DicomTag> tag; | 62 std::auto_ptr<DicomTag> tag; |
48 | 63 |
88 | 103 |
89 DicomModification::DicomModification() | 104 DicomModification::DicomModification() |
90 { | 105 { |
91 removePrivateTags_ = false; | 106 removePrivateTags_ = false; |
92 level_ = ResourceType_Instance; | 107 level_ = ResourceType_Instance; |
108 allowManualIdentifiers_ = true; | |
93 } | 109 } |
94 | 110 |
95 void DicomModification::Keep(const DicomTag& tag) | 111 void DicomModification::Keep(const DicomTag& tag) |
96 { | 112 { |
97 removals_.erase(tag); | 113 removals_.erase(tag); |
99 | 115 |
100 if (FromDcmtkBridge::IsPrivateTag(tag)) | 116 if (FromDcmtkBridge::IsPrivateTag(tag)) |
101 { | 117 { |
102 privateTagsToKeep_.insert(tag); | 118 privateTagsToKeep_.insert(tag); |
103 } | 119 } |
120 | |
121 MarkNotOrthancAnonymization(); | |
104 } | 122 } |
105 | 123 |
106 void DicomModification::Remove(const DicomTag& tag) | 124 void DicomModification::Remove(const DicomTag& tag) |
107 { | 125 { |
108 removals_.insert(tag); | 126 removals_.insert(tag); |
109 replacements_.erase(tag); | 127 replacements_.erase(tag); |
110 privateTagsToKeep_.erase(tag); | 128 privateTagsToKeep_.erase(tag); |
129 | |
130 MarkNotOrthancAnonymization(); | |
111 } | 131 } |
112 | 132 |
113 bool DicomModification::IsRemoved(const DicomTag& tag) const | 133 bool DicomModification::IsRemoved(const DicomTag& tag) const |
114 { | 134 { |
115 return removals_.find(tag) != removals_.end(); | 135 return removals_.find(tag) != removals_.end(); |
116 } | 136 } |
117 | 137 |
118 void DicomModification::Replace(const DicomTag& tag, | 138 void DicomModification::Replace(const DicomTag& tag, |
119 const std::string& value) | 139 const std::string& value, |
140 bool safeForAnonymization) | |
120 { | 141 { |
121 removals_.erase(tag); | 142 removals_.erase(tag); |
122 privateTagsToKeep_.erase(tag); | 143 privateTagsToKeep_.erase(tag); |
123 replacements_[tag] = value; | 144 replacements_[tag] = value; |
145 | |
146 if (!safeForAnonymization) | |
147 { | |
148 MarkNotOrthancAnonymization(); | |
149 } | |
124 } | 150 } |
125 | 151 |
126 bool DicomModification::IsReplaced(const DicomTag& tag) const | 152 bool DicomModification::IsReplaced(const DicomTag& tag) const |
127 { | 153 { |
128 return replacements_.find(tag) != replacements_.end(); | 154 return replacements_.find(tag) != replacements_.end(); |
143 } | 169 } |
144 | 170 |
145 void DicomModification::SetRemovePrivateTags(bool removed) | 171 void DicomModification::SetRemovePrivateTags(bool removed) |
146 { | 172 { |
147 removePrivateTags_ = removed; | 173 removePrivateTags_ = removed; |
174 | |
175 if (!removed) | |
176 { | |
177 MarkNotOrthancAnonymization(); | |
178 } | |
148 } | 179 } |
149 | 180 |
150 void DicomModification::SetLevel(ResourceType level) | 181 void DicomModification::SetLevel(ResourceType level) |
151 { | 182 { |
152 uidMap_.clear(); | 183 uidMap_.clear(); |
153 level_ = level; | 184 level_ = level; |
185 | |
186 if (level != ResourceType_Patient) | |
187 { | |
188 MarkNotOrthancAnonymization(); | |
189 } | |
154 } | 190 } |
155 | 191 |
156 void DicomModification::SetupAnonymization() | 192 void DicomModification::SetupAnonymization() |
157 { | 193 { |
158 removals_.clear(); | 194 removals_.clear(); |
217 removals_.insert(DicomTag(0x0032, 0x1032)); // Requesting Physician | 253 removals_.insert(DicomTag(0x0032, 0x1032)); // Requesting Physician |
218 removals_.insert(DicomTag(0x0010, 0x2154)); // PatientTelephoneNumbers | 254 removals_.insert(DicomTag(0x0010, 0x2154)); // PatientTelephoneNumbers |
219 removals_.insert(DicomTag(0x0010, 0x2000)); // Medical Alerts | 255 removals_.insert(DicomTag(0x0010, 0x2000)); // Medical Alerts |
220 | 256 |
221 // Set the DeidentificationMethod tag | 257 // Set the DeidentificationMethod tag |
222 replacements_.insert(std::make_pair(DicomTag(0x0012, 0x0063), "Orthanc " ORTHANC_VERSION " - PS 3.15-2008 Table E.1-1")); | 258 replacements_.insert(std::make_pair(DICOM_TAG_DEIDENTIFICATION_METHOD, ORTHANC_DEIDENTIFICATION_METHOD)); |
223 | 259 |
224 // Set the PatientIdentityRemoved tag | 260 // Set the PatientIdentityRemoved tag |
225 replacements_.insert(std::make_pair(DicomTag(0x0012, 0x0062), "YES")); | 261 replacements_.insert(std::make_pair(DicomTag(0x0012, 0x0062), "YES")); |
226 | 262 |
227 // (*) Choose a random patient name and ID | 263 // (*) Choose a random patient name and ID |
244 { | 280 { |
245 throw OrthancException(ErrorCode_BadRequest); | 281 throw OrthancException(ErrorCode_BadRequest); |
246 } | 282 } |
247 | 283 |
248 | 284 |
249 // Sanity checks | 285 // Sanity checks at the patient level |
250 if (level_ == ResourceType_Patient && !IsReplaced(DICOM_TAG_PATIENT_ID)) | 286 if (level_ == ResourceType_Patient && !IsReplaced(DICOM_TAG_PATIENT_ID)) |
251 { | 287 { |
252 LOG(ERROR) << "When modifying a patient, her PatientID is required to be modified"; | 288 LOG(ERROR) << "When modifying a patient, her PatientID is required to be modified"; |
253 throw OrthancException(ErrorCode_BadRequest); | 289 throw OrthancException(ErrorCode_BadRequest); |
254 } | 290 } |
255 | 291 |
256 if (level_ == ResourceType_Patient && IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID)) | 292 if (!allowManualIdentifiers_) |
257 { | 293 { |
258 LOG(ERROR) << "When modifying a patient, the StudyInstanceUID cannot be manually modified"; | 294 if (level_ == ResourceType_Patient && IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID)) |
259 throw OrthancException(ErrorCode_BadRequest); | 295 { |
260 } | 296 LOG(ERROR) << "When modifying a patient, the StudyInstanceUID cannot be manually modified"; |
261 | 297 throw OrthancException(ErrorCode_BadRequest); |
262 if (level_ == ResourceType_Patient && IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID)) | 298 } |
263 { | 299 |
264 LOG(ERROR) << "When modifying a patient, the SeriesInstanceUID cannot be manually modified"; | 300 if (level_ == ResourceType_Patient && IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID)) |
265 throw OrthancException(ErrorCode_BadRequest); | 301 { |
266 } | 302 LOG(ERROR) << "When modifying a patient, the SeriesInstanceUID cannot be manually modified"; |
267 | 303 throw OrthancException(ErrorCode_BadRequest); |
268 if (level_ == ResourceType_Patient && IsReplaced(DICOM_TAG_SOP_INSTANCE_UID)) | 304 } |
269 { | 305 |
270 LOG(ERROR) << "When modifying a patient, the SopInstanceUID cannot be manually modified"; | 306 if (level_ == ResourceType_Patient && IsReplaced(DICOM_TAG_SOP_INSTANCE_UID)) |
271 throw OrthancException(ErrorCode_BadRequest); | 307 { |
272 } | 308 LOG(ERROR) << "When modifying a patient, the SopInstanceUID cannot be manually modified"; |
273 | 309 throw OrthancException(ErrorCode_BadRequest); |
310 } | |
311 } | |
312 | |
313 | |
314 // Sanity checks at the study level | |
274 if (level_ == ResourceType_Study && IsReplaced(DICOM_TAG_PATIENT_ID)) | 315 if (level_ == ResourceType_Study && IsReplaced(DICOM_TAG_PATIENT_ID)) |
275 { | 316 { |
276 LOG(ERROR) << "When modifying a study, the parent PatientID cannot be manually modified"; | 317 LOG(ERROR) << "When modifying a study, the parent PatientID cannot be manually modified"; |
277 throw OrthancException(ErrorCode_BadRequest); | 318 throw OrthancException(ErrorCode_BadRequest); |
278 } | 319 } |
279 | 320 |
280 if (level_ == ResourceType_Study && IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID)) | 321 if (!allowManualIdentifiers_) |
281 { | 322 { |
282 LOG(ERROR) << "When modifying a study, the SeriesInstanceUID cannot be manually modified"; | 323 if (level_ == ResourceType_Study && IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID)) |
283 throw OrthancException(ErrorCode_BadRequest); | 324 { |
284 } | 325 LOG(ERROR) << "When modifying a study, the SeriesInstanceUID cannot be manually modified"; |
285 | 326 throw OrthancException(ErrorCode_BadRequest); |
286 if (level_ == ResourceType_Study && IsReplaced(DICOM_TAG_SOP_INSTANCE_UID)) | 327 } |
287 { | 328 |
288 LOG(ERROR) << "When modifying a study, the SopInstanceUID cannot be manually modified"; | 329 if (level_ == ResourceType_Study && IsReplaced(DICOM_TAG_SOP_INSTANCE_UID)) |
289 throw OrthancException(ErrorCode_BadRequest); | 330 { |
290 } | 331 LOG(ERROR) << "When modifying a study, the SopInstanceUID cannot be manually modified"; |
291 | 332 throw OrthancException(ErrorCode_BadRequest); |
333 } | |
334 } | |
335 | |
336 | |
337 // Sanity checks at the series level | |
292 if (level_ == ResourceType_Series && IsReplaced(DICOM_TAG_PATIENT_ID)) | 338 if (level_ == ResourceType_Series && IsReplaced(DICOM_TAG_PATIENT_ID)) |
293 { | 339 { |
294 LOG(ERROR) << "When modifying a series, the parent PatientID cannot be manually modified"; | 340 LOG(ERROR) << "When modifying a series, the parent PatientID cannot be manually modified"; |
295 throw OrthancException(ErrorCode_BadRequest); | 341 throw OrthancException(ErrorCode_BadRequest); |
296 } | 342 } |
299 { | 345 { |
300 LOG(ERROR) << "When modifying a series, the parent StudyInstanceUID cannot be manually modified"; | 346 LOG(ERROR) << "When modifying a series, the parent StudyInstanceUID cannot be manually modified"; |
301 throw OrthancException(ErrorCode_BadRequest); | 347 throw OrthancException(ErrorCode_BadRequest); |
302 } | 348 } |
303 | 349 |
304 if (level_ == ResourceType_Series && IsReplaced(DICOM_TAG_SOP_INSTANCE_UID)) | 350 if (!allowManualIdentifiers_) |
305 { | 351 { |
306 LOG(ERROR) << "When modifying a series, the SopInstanceUID cannot be manually modified"; | 352 if (level_ == ResourceType_Series && IsReplaced(DICOM_TAG_SOP_INSTANCE_UID)) |
307 throw OrthancException(ErrorCode_BadRequest); | 353 { |
308 } | 354 LOG(ERROR) << "When modifying a series, the SopInstanceUID cannot be manually modified"; |
309 | 355 throw OrthancException(ErrorCode_BadRequest); |
356 } | |
357 } | |
358 | |
359 | |
360 // Sanity checks at the instance level | |
310 if (level_ == ResourceType_Instance && IsReplaced(DICOM_TAG_PATIENT_ID)) | 361 if (level_ == ResourceType_Instance && IsReplaced(DICOM_TAG_PATIENT_ID)) |
311 { | 362 { |
312 LOG(ERROR) << "When modifying an instance, the parent PatientID cannot be manually modified"; | 363 LOG(ERROR) << "When modifying an instance, the parent PatientID cannot be manually modified"; |
313 throw OrthancException(ErrorCode_BadRequest); | 364 throw OrthancException(ErrorCode_BadRequest); |
314 } | 365 } |
345 { | 396 { |
346 toModify.Replace(it->first, it->second, DicomReplaceMode_InsertIfAbsent); | 397 toModify.Replace(it->first, it->second, DicomReplaceMode_InsertIfAbsent); |
347 } | 398 } |
348 | 399 |
349 // (4) Update the DICOM identifiers | 400 // (4) Update the DICOM identifiers |
350 if (level_ <= ResourceType_Study) | 401 if (level_ <= ResourceType_Study && |
402 !IsReplaced(DICOM_TAG_STUDY_INSTANCE_UID)) | |
351 { | 403 { |
352 MapDicomIdentifier(toModify, ResourceType_Study); | 404 MapDicomIdentifier(toModify, ResourceType_Study); |
353 } | 405 } |
354 | 406 |
355 if (level_ <= ResourceType_Series) | 407 if (level_ <= ResourceType_Series && |
408 !IsReplaced(DICOM_TAG_SERIES_INSTANCE_UID)) | |
356 { | 409 { |
357 MapDicomIdentifier(toModify, ResourceType_Series); | 410 MapDicomIdentifier(toModify, ResourceType_Series); |
358 } | 411 } |
359 | 412 |
360 if (level_ <= ResourceType_Instance) // Always true | 413 if (level_ <= ResourceType_Instance && // Always true |
414 !IsReplaced(DICOM_TAG_SOP_INSTANCE_UID)) | |
361 { | 415 { |
362 MapDicomIdentifier(toModify, ResourceType_Instance); | 416 MapDicomIdentifier(toModify, ResourceType_Instance); |
363 } | 417 } |
364 } | 418 } |
365 } | 419 } |