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 }