comparison OrthancServer/OrthancRestApi.cpp @ 515:a8be42bcf2bb

Link from modified to original resource in Orthanc Explorer
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 19 Aug 2013 13:40:36 +0200
parents 7db04aa5104f
children 1b2cdc855bd3
comparison
equal deleted inserted replaced
513:935e8c7e0b18 515:a8be42bcf2bb
1029 if (!removals.isArray()) 1029 if (!removals.isArray())
1030 { 1030 {
1031 throw OrthancException(ErrorCode_BadRequest); 1031 throw OrthancException(ErrorCode_BadRequest);
1032 } 1032 }
1033 1033
1034 target.clear();
1035
1036 for (Json::Value::ArrayIndex i = 0; i < removals.size(); i++) 1034 for (Json::Value::ArrayIndex i = 0; i < removals.size(); i++)
1037 { 1035 {
1038 std::string name = removals[i].asString(); 1036 std::string name = removals[i].asString();
1039 DicomTag tag = FromDcmtkBridge::ParseTag(name); 1037 DicomTag tag = FromDcmtkBridge::ParseTag(name);
1040 target.insert(tag); 1038 target.insert(tag);
1049 { 1047 {
1050 if (!replacements.isObject()) 1048 if (!replacements.isObject())
1051 { 1049 {
1052 throw OrthancException(ErrorCode_BadRequest); 1050 throw OrthancException(ErrorCode_BadRequest);
1053 } 1051 }
1054
1055 target.clear();
1056 1052
1057 Json::Value::Members members = replacements.getMemberNames(); 1053 Json::Value::Members members = replacements.getMemberNames();
1058 for (size_t i = 0; i < members.size(); i++) 1054 for (size_t i = 0; i < members.size(); i++)
1059 { 1055 {
1060 const std::string& name = members[i]; 1056 const std::string& name = members[i];
1097 removals.insert(DicomTag(0x0008, 0x1070)); // Operators' Name 1093 removals.insert(DicomTag(0x0008, 0x1070)); // Operators' Name
1098 removals.insert(DicomTag(0x0008, 0x1080)); // Admitting Diagnoses Description 1094 removals.insert(DicomTag(0x0008, 0x1080)); // Admitting Diagnoses Description
1099 removals.insert(DicomTag(0x0008, 0x1155)); // Referenced SOP Instance UID 1095 removals.insert(DicomTag(0x0008, 0x1155)); // Referenced SOP Instance UID
1100 removals.insert(DicomTag(0x0008, 0x2111)); // Derivation Description 1096 removals.insert(DicomTag(0x0008, 0x2111)); // Derivation Description
1101 removals.insert(DicomTag(0x0010, 0x0010)); // Patient's Name 1097 removals.insert(DicomTag(0x0010, 0x0010)); // Patient's Name
1102 removals.insert(DicomTag(0x0010, 0x0020)); // Patient ID 1098 //removals.insert(DicomTag(0x0010, 0x0020)); // Patient ID => cf. below (*)
1103 removals.insert(DicomTag(0x0010, 0x0030)); // Patient's Birth Date 1099 removals.insert(DicomTag(0x0010, 0x0030)); // Patient's Birth Date
1104 removals.insert(DicomTag(0x0010, 0x0032)); // Patient's Birth Time 1100 removals.insert(DicomTag(0x0010, 0x0032)); // Patient's Birth Time
1105 removals.insert(DicomTag(0x0010, 0x0040)); // Patient's Sex 1101 removals.insert(DicomTag(0x0010, 0x0040)); // Patient's Sex
1106 removals.insert(DicomTag(0x0010, 0x1000)); // Other Patient Ids 1102 removals.insert(DicomTag(0x0010, 0x1000)); // Other Patient Ids
1107 removals.insert(DicomTag(0x0010, 0x1001)); // Other Patient Names 1103 removals.insert(DicomTag(0x0010, 0x1001)); // Other Patient Names
1113 removals.insert(DicomTag(0x0010, 0x2180)); // Occupation 1109 removals.insert(DicomTag(0x0010, 0x2180)); // Occupation
1114 removals.insert(DicomTag(0x0010, 0x21b0)); // Additional Patient's History 1110 removals.insert(DicomTag(0x0010, 0x21b0)); // Additional Patient's History
1115 removals.insert(DicomTag(0x0010, 0x4000)); // Patient Comments 1111 removals.insert(DicomTag(0x0010, 0x4000)); // Patient Comments
1116 removals.insert(DicomTag(0x0018, 0x1000)); // Device Serial Number 1112 removals.insert(DicomTag(0x0018, 0x1000)); // Device Serial Number
1117 removals.insert(DicomTag(0x0018, 0x1030)); // Protocol Name 1113 removals.insert(DicomTag(0x0018, 0x1030)); // Protocol Name
1118 //removals.insert(DicomTag(0x0020, 0x000d)); // Study Instance UID => generated below 1114 //removals.insert(DicomTag(0x0020, 0x000d)); // Study Instance UID => cf. below (*)
1119 //removals.insert(DicomTag(0x0020, 0x000e)); // Series Instance UID => generated below 1115 //removals.insert(DicomTag(0x0020, 0x000e)); // Series Instance UID => cf. below (*)
1120 removals.insert(DicomTag(0x0020, 0x0010)); // Study ID 1116 removals.insert(DicomTag(0x0020, 0x0010)); // Study ID
1121 removals.insert(DicomTag(0x0020, 0x0052)); // Frame of Reference UID 1117 removals.insert(DicomTag(0x0020, 0x0052)); // Frame of Reference UID
1122 removals.insert(DicomTag(0x0020, 0x0200)); // Synchronization Frame of Reference UID 1118 removals.insert(DicomTag(0x0020, 0x0200)); // Synchronization Frame of Reference UID
1123 removals.insert(DicomTag(0x0020, 0x4000)); // Image Comments 1119 removals.insert(DicomTag(0x0020, 0x4000)); // Image Comments
1124 removals.insert(DicomTag(0x0040, 0x0275)); // Request Attributes Sequence 1120 removals.insert(DicomTag(0x0040, 0x0275)); // Request Attributes Sequence
1126 removals.insert(DicomTag(0x0040, 0xa730)); // Content Sequence 1122 removals.insert(DicomTag(0x0040, 0xa730)); // Content Sequence
1127 removals.insert(DicomTag(0x0088, 0x0140)); // Storage Media File-set UID 1123 removals.insert(DicomTag(0x0088, 0x0140)); // Storage Media File-set UID
1128 removals.insert(DicomTag(0x3006, 0x0024)); // Referenced Frame of Reference UID 1124 removals.insert(DicomTag(0x3006, 0x0024)); // Referenced Frame of Reference UID
1129 removals.insert(DicomTag(0x3006, 0x00c2)); // Related Frame of Reference UID 1125 removals.insert(DicomTag(0x3006, 0x00c2)); // Related Frame of Reference UID
1130 1126
1127 /**
1128 * (*) Patient ID, Study Instance UID and Series Instance UID
1129 * are modified by "AnonymizeInstance()" if anonymizing a single
1130 * instance, or by "RetrieveMappedUid()" if anonymizing a
1131 * patient/study/series.
1132 **/
1133
1134
1131 // Some more removals (from the experience of DICOM files at the CHU of Liege) 1135 // Some more removals (from the experience of DICOM files at the CHU of Liege)
1132 removals.insert(DicomTag(0x0010, 0x1040)); // Patient's Address 1136 removals.insert(DicomTag(0x0010, 0x1040)); // Patient's Address
1133 removals.insert(DicomTag(0x0032, 0x1032)); // Requesting Physician 1137 removals.insert(DicomTag(0x0032, 0x1032)); // Requesting Physician
1134 removals.insert(DicomTag(0x0010, 0x2154)); // PatientTelephoneNumbers 1138 removals.insert(DicomTag(0x0010, 0x2154)); // PatientTelephoneNumbers
1135 1139
1136 // Set the DeidentificationMethod tag 1140 // Set the DeidentificationMethod tag
1137 replacements.insert(std::make_pair(DicomTag(0x0012, 0x0063), "Orthanc " ORTHANC_VERSION " - PS 3.15-2008 Table E.1-1")); 1141 replacements.insert(std::make_pair(DicomTag(0x0012, 0x0063), "Orthanc " ORTHANC_VERSION " - PS 3.15-2008 Table E.1-1"));
1138 1142
1139 // Set the PatientIdentityRemoved 1143 // Set the PatientIdentityRemoved tag
1140 replacements.insert(std::make_pair(DicomTag(0x0012, 0x0062), "YES")); 1144 replacements.insert(std::make_pair(DicomTag(0x0012, 0x0062), "YES"));
1141
1142 // Generate random study UID if not specified
1143 if (replacements.find(DICOM_TAG_STUDY_INSTANCE_UID) == replacements.end())
1144 {
1145 replacements.insert(std::make_pair(DICOM_TAG_STUDY_INSTANCE_UID,
1146 FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study)));
1147 }
1148
1149 // Generate random series UID if not specified
1150 if (replacements.find(DICOM_TAG_SERIES_INSTANCE_UID) == replacements.end())
1151 {
1152 replacements.insert(std::make_pair(DICOM_TAG_SERIES_INSTANCE_UID,
1153 FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series)));
1154 }
1155 } 1145 }
1156 1146
1157 1147
1158 static bool ParseModifyRequest(Removals& removals, 1148 static bool ParseModifyRequest(Removals& removals,
1159 Replacements& replacements, 1149 Replacements& replacements,
1250 1240
1251 // Generate random Patient's Name if none is specified 1241 // Generate random Patient's Name if none is specified
1252 if (replacements.find(DicomTag(0x0010, 0x0010)) == replacements.end()) 1242 if (replacements.find(DicomTag(0x0010, 0x0010)) == replacements.end())
1253 { 1243 {
1254 replacements.insert(std::make_pair(DicomTag(0x0010, 0x0010), GeneratePatientName(context))); 1244 replacements.insert(std::make_pair(DicomTag(0x0010, 0x0010), GeneratePatientName(context)));
1255 }
1256
1257 // Generate random Patient's ID if none is specified
1258 if (replacements.find(DICOM_TAG_PATIENT_ID) == replacements.end())
1259 {
1260 replacements.insert(std::make_pair(DICOM_TAG_PATIENT_ID,
1261 FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Patient)));
1262 } 1245 }
1263 1246
1264 return true; 1247 return true;
1265 } 1248 }
1266 else 1249 else
1291 DicomRootLevel level, 1274 DicomRootLevel level,
1292 Replacements& replacements, 1275 Replacements& replacements,
1293 UidMap& uidMap) 1276 UidMap& uidMap)
1294 { 1277 {
1295 std::auto_ptr<DicomTag> tag; 1278 std::auto_ptr<DicomTag> tag;
1296 if (level == DicomRootLevel_Series) 1279
1297 { 1280 switch (level)
1298 tag.reset(new DicomTag(DICOM_TAG_SERIES_INSTANCE_UID)); 1281 {
1299 } 1282 case DicomRootLevel_Series:
1300 else 1283 tag.reset(new DicomTag(DICOM_TAG_SERIES_INSTANCE_UID));
1301 { 1284 break;
1302 assert(level == DicomRootLevel_Study); 1285
1303 tag.reset(new DicomTag(DICOM_TAG_STUDY_INSTANCE_UID)); 1286 case DicomRootLevel_Study:
1287 tag.reset(new DicomTag(DICOM_TAG_STUDY_INSTANCE_UID));
1288 break;
1289
1290 case DicomRootLevel_Patient:
1291 tag.reset(new DicomTag(DICOM_TAG_PATIENT_ID));
1292 break;
1293
1294 default:
1295 throw OrthancException(ErrorCode_InternalError);
1304 } 1296 }
1305 1297
1306 std::string original; 1298 std::string original;
1307 if (!dicom.GetTagValue(original, *tag)) 1299 if (!dicom.GetTagValue(original, *tag))
1308 { 1300 {
1328 replacements[*tag] = mapped; 1320 replacements[*tag] = mapped;
1329 return isNew; 1321 return isNew;
1330 } 1322 }
1331 1323
1332 1324
1333 static void AnonymizeOrModifyResource(Removals& removals, 1325 static void AnonymizeOrModifyResource(bool isAnonymization,
1326 Removals& removals,
1334 Replacements& replacements, 1327 Replacements& replacements,
1335 bool removePrivateTags, 1328 bool removePrivateTags,
1336 MetadataType metadataType, 1329 MetadataType metadataType,
1337 ChangeType changeType, 1330 ChangeType changeType,
1338 ResourceType resourceType, 1331 ResourceType resourceType,
1365 it != instances.end(); it++) 1358 it != instances.end(); it++)
1366 { 1359 {
1367 LOG(INFO) << "Modifying instance " << *it; 1360 LOG(INFO) << "Modifying instance " << *it;
1368 ParsedDicomFile& original = context.GetDicomFile(*it); 1361 ParsedDicomFile& original = context.GetDicomFile(*it);
1369 1362
1363 DicomInstanceHasher originalHasher = original.GetHasher();
1364
1365 if (isFirst && !isAnonymization)
1366 {
1367 // If modifying a study or a series, keep the original patient ID.
1368 std::string patientId = originalHasher.GetPatientId();
1369 uidMap[std::make_pair(DicomRootLevel_Patient, patientId)] = patientId;
1370 }
1371
1370 bool isNewSeries = RetrieveMappedUid(original, DicomRootLevel_Series, replacements, uidMap); 1372 bool isNewSeries = RetrieveMappedUid(original, DicomRootLevel_Series, replacements, uidMap);
1371 1373 bool isNewStudy = RetrieveMappedUid(original, DicomRootLevel_Study, replacements, uidMap);
1372 bool isNewStudy = false; 1374 bool isNewPatient = RetrieveMappedUid(original, DicomRootLevel_Patient, replacements, uidMap);
1373 if (resourceType == ResourceType_Study || 1375
1374 resourceType == ResourceType_Patient)
1375 {
1376 isNewStudy = RetrieveMappedUid(original, DicomRootLevel_Study, replacements, uidMap);
1377 }
1378 1376
1379 /** 1377 /**
1380 * Compute the resulting DICOM instance and store it into the Orthanc store. 1378 * Compute the resulting DICOM instance and store it into the Orthanc store.
1381 **/ 1379 **/
1382 1380
1394 /** 1392 /**
1395 * Record metadata information (AnonymizedFrom/ModifiedFrom). 1393 * Record metadata information (AnonymizedFrom/ModifiedFrom).
1396 **/ 1394 **/
1397 1395
1398 DicomInstanceHasher modifiedHasher = modified->GetHasher(); 1396 DicomInstanceHasher modifiedHasher = modified->GetHasher();
1399 DicomInstanceHasher originalHasher = original.GetHasher();
1400 1397
1401 if (isNewSeries) 1398 if (isNewSeries)
1402 { 1399 {
1403 context.GetIndex().SetMetadata(modifiedHasher.HashSeries(), 1400 context.GetIndex().SetMetadata(modifiedHasher.HashSeries(),
1404 metadataType, originalHasher.HashSeries()); 1401 metadataType, originalHasher.HashSeries());
1406 1403
1407 if (isNewStudy) 1404 if (isNewStudy)
1408 { 1405 {
1409 context.GetIndex().SetMetadata(modifiedHasher.HashStudy(), 1406 context.GetIndex().SetMetadata(modifiedHasher.HashStudy(),
1410 metadataType, originalHasher.HashStudy()); 1407 metadataType, originalHasher.HashStudy());
1408 }
1409
1410 if (isNewPatient)
1411 {
1412 context.GetIndex().SetMetadata(modifiedHasher.HashPatient(),
1413 metadataType, originalHasher.HashPatient());
1411 } 1414 }
1412 1415
1413 assert(*it == originalHasher.HashInstance()); 1416 assert(*it == originalHasher.HashInstance());
1414 assert(modifiedInstance == modifiedHasher.HashInstance()); 1417 assert(modifiedInstance == modifiedHasher.HashInstance());
1415 context.GetIndex().SetMetadata(modifiedInstance, metadataType, *it); 1418 context.GetIndex().SetMetadata(modifiedInstance, metadataType, *it);
1419 * Compute the JSON object that is returned by the REST call. 1422 * Compute the JSON object that is returned by the REST call.
1420 **/ 1423 **/
1421 1424
1422 if (isFirst) 1425 if (isFirst)
1423 { 1426 {
1424 context.GetIndex().SetMetadata(modifiedHasher.HashPatient(),
1425 metadataType, originalHasher.HashPatient());
1426
1427 std::string newId; 1427 std::string newId;
1428 1428
1429 switch (resourceType) 1429 switch (resourceType)
1430 { 1430 {
1431 case ResourceType_Series: 1431 case ResourceType_Series:
1476 Replacements replacements; 1476 Replacements replacements;
1477 bool removePrivateTags; 1477 bool removePrivateTags;
1478 1478
1479 if (ParseAnonymizationRequest(removals, replacements, removePrivateTags, call)) 1479 if (ParseAnonymizationRequest(removals, replacements, removePrivateTags, call))
1480 { 1480 {
1481 // Generate random patient ID if not specified
1482 if (replacements.find(DICOM_TAG_PATIENT_ID) == replacements.end())
1483 {
1484 replacements.insert(std::make_pair(DICOM_TAG_PATIENT_ID,
1485 FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Patient)));
1486 }
1487
1488 // Generate random study UID if not specified
1489 if (replacements.find(DICOM_TAG_STUDY_INSTANCE_UID) == replacements.end())
1490 {
1491 replacements.insert(std::make_pair(DICOM_TAG_STUDY_INSTANCE_UID,
1492 FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study)));
1493 }
1494
1495 // Generate random series UID if not specified
1496 if (replacements.find(DICOM_TAG_SERIES_INSTANCE_UID) == replacements.end())
1497 {
1498 replacements.insert(std::make_pair(DICOM_TAG_SERIES_INSTANCE_UID,
1499 FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series)));
1500 }
1501
1481 AnonymizeOrModifyInstance(removals, replacements, removePrivateTags, call); 1502 AnonymizeOrModifyInstance(removals, replacements, removePrivateTags, call);
1482 } 1503 }
1483 } 1504 }
1484 1505
1485 1506
1489 Replacements replacements; 1510 Replacements replacements;
1490 bool removePrivateTags; 1511 bool removePrivateTags;
1491 1512
1492 if (ParseModifyRequest(removals, replacements, removePrivateTags, call)) 1513 if (ParseModifyRequest(removals, replacements, removePrivateTags, call))
1493 { 1514 {
1494 AnonymizeOrModifyResource(removals, replacements, removePrivateTags, 1515 AnonymizeOrModifyResource(false, removals, replacements, removePrivateTags,
1495 MetadataType_ModifiedFrom, ChangeType_ModifiedSeries, 1516 MetadataType_ModifiedFrom, ChangeType_ModifiedSeries,
1496 ResourceType_Series, call); 1517 ResourceType_Series, call);
1497 } 1518 }
1498 } 1519 }
1499 1520
1504 Replacements replacements; 1525 Replacements replacements;
1505 bool removePrivateTags; 1526 bool removePrivateTags;
1506 1527
1507 if (ParseAnonymizationRequest(removals, replacements, removePrivateTags, call)) 1528 if (ParseAnonymizationRequest(removals, replacements, removePrivateTags, call))
1508 { 1529 {
1509 AnonymizeOrModifyResource(removals, replacements, removePrivateTags, 1530 AnonymizeOrModifyResource(true, removals, replacements, removePrivateTags,
1510 MetadataType_AnonymizedFrom, ChangeType_AnonymizedSeries, 1531 MetadataType_AnonymizedFrom, ChangeType_AnonymizedSeries,
1511 ResourceType_Series, call); 1532 ResourceType_Series, call);
1512 } 1533 }
1513 } 1534 }
1514 1535
1519 Replacements replacements; 1540 Replacements replacements;
1520 bool removePrivateTags; 1541 bool removePrivateTags;
1521 1542
1522 if (ParseModifyRequest(removals, replacements, removePrivateTags, call)) 1543 if (ParseModifyRequest(removals, replacements, removePrivateTags, call))
1523 { 1544 {
1524 AnonymizeOrModifyResource(removals, replacements, removePrivateTags, 1545 AnonymizeOrModifyResource(false, removals, replacements, removePrivateTags,
1525 MetadataType_ModifiedFrom, ChangeType_ModifiedStudy, 1546 MetadataType_ModifiedFrom, ChangeType_ModifiedStudy,
1526 ResourceType_Study, call); 1547 ResourceType_Study, call);
1527 } 1548 }
1528 } 1549 }
1529 1550
1534 Replacements replacements; 1555 Replacements replacements;
1535 bool removePrivateTags; 1556 bool removePrivateTags;
1536 1557
1537 if (ParseAnonymizationRequest(removals, replacements, removePrivateTags, call)) 1558 if (ParseAnonymizationRequest(removals, replacements, removePrivateTags, call))
1538 { 1559 {
1539 AnonymizeOrModifyResource(removals, replacements, removePrivateTags, 1560 AnonymizeOrModifyResource(true, removals, replacements, removePrivateTags,
1540 MetadataType_AnonymizedFrom, ChangeType_AnonymizedStudy, 1561 MetadataType_AnonymizedFrom, ChangeType_AnonymizedStudy,
1541 ResourceType_Study, call); 1562 ResourceType_Study, call);
1542 } 1563 }
1543 } 1564 }
1544 1565
1545 1566
1546 static void ModifyPatientInplace(RestApi::PostCall& call) 1567 /*static void ModifyPatientInplace(RestApi::PostCall& call)
1547 { 1568 {
1548 Removals removals; 1569 Removals removals;
1549 Replacements replacements; 1570 Replacements replacements;
1550 bool removePrivateTags; 1571 bool removePrivateTags;
1551 1572
1552 if (ParseModifyRequest(removals, replacements, removePrivateTags, call)) 1573 if (ParseModifyRequest(removals, replacements, removePrivateTags, call))
1553 { 1574 {
1554 AnonymizeOrModifyResource(removals, replacements, removePrivateTags, 1575 AnonymizeOrModifyResource(false, removals, replacements, removePrivateTags,
1555 MetadataType_ModifiedFrom, ChangeType_ModifiedPatient, 1576 MetadataType_ModifiedFrom, ChangeType_ModifiedPatient,
1556 ResourceType_Patient, call); 1577 ResourceType_Patient, call);
1557 } 1578 }
1558 } 1579 }*/
1559 1580
1560 1581
1561 static void AnonymizePatientInplace(RestApi::PostCall& call) 1582 static void AnonymizePatientInplace(RestApi::PostCall& call)
1562 { 1583 {
1563 Removals removals; 1584 Removals removals;
1564 Replacements replacements; 1585 Replacements replacements;
1565 bool removePrivateTags; 1586 bool removePrivateTags;
1566 1587
1567 if (ParseAnonymizationRequest(removals, replacements, removePrivateTags, call)) 1588 if (ParseAnonymizationRequest(removals, replacements, removePrivateTags, call))
1568 { 1589 {
1569 AnonymizeOrModifyResource(removals, replacements, removePrivateTags, 1590 AnonymizeOrModifyResource(true, removals, replacements, removePrivateTags,
1570 MetadataType_AnonymizedFrom, ChangeType_AnonymizedPatient, 1591 MetadataType_AnonymizedFrom, ChangeType_AnonymizedPatient,
1571 ResourceType_Patient, call); 1592 ResourceType_Patient, call);
1572 } 1593 }
1573 } 1594 }
1574 1595
1832 Register("/peers/{id}/store", PeerStore); 1853 Register("/peers/{id}/store", PeerStore);
1833 1854
1834 Register("/instances/{id}/modify", ModifyInstance); 1855 Register("/instances/{id}/modify", ModifyInstance);
1835 Register("/series/{id}/modify", ModifySeriesInplace); 1856 Register("/series/{id}/modify", ModifySeriesInplace);
1836 Register("/studies/{id}/modify", ModifyStudyInplace); 1857 Register("/studies/{id}/modify", ModifyStudyInplace);
1837 Register("/patients/{id}/modify", ModifyPatientInplace); 1858 //Register("/patients/{id}/modify", ModifyPatientInplace);
1838 1859
1839 Register("/instances/{id}/anonymize", AnonymizeInstance); 1860 Register("/instances/{id}/anonymize", AnonymizeInstance);
1840 Register("/series/{id}/anonymize", AnonymizeSeriesInplace); 1861 Register("/series/{id}/anonymize", AnonymizeSeriesInplace);
1841 Register("/studies/{id}/anonymize", AnonymizeStudyInplace); 1862 Register("/studies/{id}/anonymize", AnonymizeStudyInplace);
1842 Register("/patients/{id}/anonymize", AnonymizePatientInplace); 1863 Register("/patients/{id}/anonymize", AnonymizePatientInplace);