comparison OrthancServer/OrthancRestApi.cpp @ 312:1642a354fec8

flexible
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 21 Dec 2012 13:36:50 +0100
parents 26efccdff583
children 60429bb2551e
comparison
equal deleted inserted replaced
311:26efccdff583 312:1642a354fec8
848 } 848 }
849 849
850 static void ReplaceInstanceInternal(ParsedDicomFile& toModify, 850 static void ReplaceInstanceInternal(ParsedDicomFile& toModify,
851 const Removals& removals, 851 const Removals& removals,
852 const Replacements& replacements, 852 const Replacements& replacements,
853 DicomReplaceMode mode) 853 DicomReplaceMode mode,
854 { 854 bool removePrivateTags)
855 {
856 if (removePrivateTags)
857 {
858 toModify.RemovePrivateTags();
859 }
860
855 for (Removals::const_iterator it = removals.begin(); 861 for (Removals::const_iterator it = removals.begin();
856 it != removals.end(); it++) 862 it != removals.end(); it++)
857 { 863 {
858 toModify.Remove(*it); 864 toModify.Remove(*it);
859 } 865 }
918 924
919 925
920 static void SetupAnonymization(Removals& removals, 926 static void SetupAnonymization(Removals& removals,
921 Replacements& replacements) 927 Replacements& replacements)
922 { 928 {
923 removals.clear();
924 replacements.clear();
925
926 // This is Table E.1-1 from PS 3.15-2008 - DICOM Part 15: Security and System Management Profiles 929 // This is Table E.1-1 from PS 3.15-2008 - DICOM Part 15: Security and System Management Profiles
927 removals.insert(DicomTag(0x0008, 0x0014)); // Instance Creator UID 930 removals.insert(DicomTag(0x0008, 0x0014)); // Instance Creator UID
928 //removals.insert(DicomTag(0x0008, 0x0018)); // SOP Instance UID => set by ReplaceInstanceInternal() 931 //removals.insert(DicomTag(0x0008, 0x0018)); // SOP Instance UID => set by ReplaceInstanceInternal()
929 removals.insert(DicomTag(0x0008, 0x0050)); // Accession Number 932 removals.insert(DicomTag(0x0008, 0x0050)); // Accession Number
930 removals.insert(DicomTag(0x0008, 0x0080)); // Institution Name 933 removals.insert(DicomTag(0x0008, 0x0080)); // Institution Name
990 } 993 }
991 994
992 995
993 static bool ParseModifyRequest(Removals& removals, 996 static bool ParseModifyRequest(Removals& removals,
994 Replacements& replacements, 997 Replacements& replacements,
998 bool& removePrivateTags,
995 const RestApi::PostCall& call) 999 const RestApi::PostCall& call)
996 { 1000 {
1001 removePrivateTags = false;
997 Json::Value request; 1002 Json::Value request;
998 if (call.ParseJsonRequest(request) && 1003 if (call.ParseJsonRequest(request) &&
999 request.isObject()) 1004 request.isObject())
1000 { 1005 {
1001 Json::Value removalsPart = Json::arrayValue; 1006 Json::Value removalsPart = Json::arrayValue;
1009 if (request.isMember("Replace")) 1014 if (request.isMember("Replace"))
1010 { 1015 {
1011 replacementsPart = request["Replace"]; 1016 replacementsPart = request["Replace"];
1012 } 1017 }
1013 1018
1019 if (request.isMember("RemovePrivateTags"))
1020 {
1021 removePrivateTags = true;
1022 }
1023
1014 ParseRemovals(removals, removalsPart); 1024 ParseRemovals(removals, removalsPart);
1015 ParseReplacements(replacements, replacementsPart); 1025 ParseReplacements(replacements, replacementsPart);
1016 1026
1017 return true; 1027 return true;
1018 } 1028 }
1033 Json::Value request; 1043 Json::Value request;
1034 if (call.ParseJsonRequest(request) && 1044 if (call.ParseJsonRequest(request) &&
1035 request.isObject()) 1045 request.isObject())
1036 { 1046 {
1037 Json::Value keepPart = Json::arrayValue; 1047 Json::Value keepPart = Json::arrayValue;
1048 Json::Value removalsPart = Json::arrayValue;
1049 Json::Value replacementsPart = Json::objectValue;
1050
1038 if (request.isMember("Keep")) 1051 if (request.isMember("Keep"))
1039 { 1052 {
1040 keepPart = request["Keep"]; 1053 keepPart = request["Keep"];
1041 } 1054 }
1042 1055
1043 if (request.isMember("KeepPrivateTags")) 1056 if (request.isMember("KeepPrivateTags"))
1044 { 1057 {
1045 removePrivateTags = false; 1058 removePrivateTags = false;
1059 }
1060
1061 if (request.isMember("Replace"))
1062 {
1063 replacementsPart = request["Replace"];
1046 } 1064 }
1047 1065
1048 Removals toKeep; 1066 Removals toKeep;
1049 ParseRemovals(toKeep, keepPart); 1067 ParseRemovals(toKeep, keepPart);
1050 1068
1053 for (Removals::iterator it = toKeep.begin(); it != toKeep.end(); it++) 1071 for (Removals::iterator it = toKeep.begin(); it != toKeep.end(); it++)
1054 { 1072 {
1055 removals.erase(*it); 1073 removals.erase(*it);
1056 } 1074 }
1057 1075
1076 Removals additionalRemovals;
1077 ParseRemovals(additionalRemovals, removalsPart);
1078
1079 for (Removals::iterator it = additionalRemovals.begin();
1080 it != additionalRemovals.end(); it++)
1081 {
1082 removals.erase(*it);
1083 }
1084
1085 ParseReplacements(replacements, replacementsPart);
1086
1058 return true; 1087 return true;
1059 } 1088 }
1060 else 1089 else
1061 { 1090 {
1062 return false; 1091 return false;
1063 } 1092 }
1064 } 1093 }
1065 1094
1066 1095
1067 static void ModifyInstance(RestApi::PostCall& call) 1096 static void ModifyInstance(RestApi::PostCall& call)
1068 {
1069 RETRIEVE_CONTEXT(call);
1070
1071 std::string id = call.GetUriComponent("id", "");
1072 ParsedDicomFile& dicom = context.GetDicomFile(id);
1073
1074 Removals removals;
1075 Replacements replacements;
1076
1077 if (ParseModifyRequest(removals, replacements, call))
1078 {
1079 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone());
1080 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent);
1081 context.GetIndex().SetMetadata(id, MetadataType_ModifiedFrom, id);
1082 modified->Answer(call.GetOutput());
1083 }
1084 }
1085
1086
1087 static void AnonymizeInstance(RestApi::PostCall& call)
1088 { 1097 {
1089 RETRIEVE_CONTEXT(call); 1098 RETRIEVE_CONTEXT(call);
1090 1099
1091 std::string id = call.GetUriComponent("id", ""); 1100 std::string id = call.GetUriComponent("id", "");
1092 ParsedDicomFile& dicom = context.GetDicomFile(id); 1101 ParsedDicomFile& dicom = context.GetDicomFile(id);
1093 1102
1094 Removals removals; 1103 Removals removals;
1095 Replacements replacements; 1104 Replacements replacements;
1096 bool removePrivateTags; 1105 bool removePrivateTags;
1097 1106
1107 if (ParseModifyRequest(removals, replacements, removePrivateTags, call))
1108 {
1109 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone());
1110 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags);
1111 context.GetIndex().SetMetadata(id, MetadataType_ModifiedFrom, id);
1112 modified->Answer(call.GetOutput());
1113 }
1114 }
1115
1116
1117 static void AnonymizeInstance(RestApi::PostCall& call)
1118 {
1119 RETRIEVE_CONTEXT(call);
1120
1121 std::string id = call.GetUriComponent("id", "");
1122 ParsedDicomFile& dicom = context.GetDicomFile(id);
1123
1124 Removals removals;
1125 Replacements replacements;
1126 bool removePrivateTags;
1127
1098 if (ParseAnonymizationRequest(removals, replacements, removePrivateTags, call)) 1128 if (ParseAnonymizationRequest(removals, replacements, removePrivateTags, call))
1099 { 1129 {
1100 // Generate random Patient's name 1130 // Generate random Patient's Name if none is specified
1101 removals.erase(DicomTag(0x0010, 0x0010)); 1131 if (replacements.find(DicomTag(0x0010, 0x0010)) == replacements.end())
1102 replacements.insert(std::make_pair(DicomTag(0x0010, 0x0010), GeneratePatientName(context))); 1132 {
1103 1133 replacements.insert(std::make_pair(DicomTag(0x0010, 0x0010), GeneratePatientName(context)));
1104 // Generate random Patient ID 1134 }
1105 removals.erase(DICOM_TAG_PATIENT_ID); 1135
1106 replacements.insert(std::make_pair(DICOM_TAG_PATIENT_ID, 1136 // Generate random Patient's ID if none is specified
1107 FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Patient))); 1137 if (replacements.find(DICOM_TAG_PATIENT_ID) == replacements.end())
1138 {
1139 replacements.insert(std::make_pair(DICOM_TAG_PATIENT_ID,
1140 FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Patient)));
1141 }
1108 1142
1109 std::auto_ptr<ParsedDicomFile> anonymized(dicom.Clone()); 1143 std::auto_ptr<ParsedDicomFile> anonymized(dicom.Clone());
1110 1144 ReplaceInstanceInternal(*anonymized, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags);
1111 if (removePrivateTags)
1112 {
1113 anonymized->RemovePrivateTags();
1114 }
1115
1116 ReplaceInstanceInternal(*anonymized, removals, replacements, DicomReplaceMode_InsertIfAbsent);
1117 context.GetIndex().SetMetadata(id, MetadataType_AnonymizedFrom, id); 1145 context.GetIndex().SetMetadata(id, MetadataType_AnonymizedFrom, id);
1118 1146
1119 anonymized->Answer(call.GetOutput()); 1147 anonymized->Answer(call.GetOutput());
1120 } 1148 }
1121 } 1149 }
1135 return; 1163 return;
1136 } 1164 }
1137 1165
1138 Removals removals; 1166 Removals removals;
1139 Replacements replacements; 1167 Replacements replacements;
1140 1168 bool removePrivateTags;
1141 if (ParseModifyRequest(removals, replacements, call)) 1169
1170 if (ParseModifyRequest(removals, replacements, removePrivateTags, call))
1142 { 1171 {
1143 std::string newSeriesId; 1172 std::string newSeriesId;
1144 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); 1173 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series);
1145 1174
1146 for (Instances::const_iterator it = instances.begin(); 1175 for (Instances::const_iterator it = instances.begin();
1147 it != instances.end(); it++) 1176 it != instances.end(); it++)
1148 { 1177 {
1149 LOG(INFO) << "Modifying instance " << *it; 1178 LOG(INFO) << "Modifying instance " << *it;
1150 ParsedDicomFile& dicom = context.GetDicomFile(*it); 1179 ParsedDicomFile& dicom = context.GetDicomFile(*it);
1151 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); 1180 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone());
1152 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent); 1181 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags);
1153 1182
1154 std::string modifiedInstance; 1183 std::string modifiedInstance;
1155 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) 1184 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success)
1156 { 1185 {
1157 LOG(ERROR) << "Error while storing a modified instance " << *it; 1186 LOG(ERROR) << "Error while storing a modified instance " << *it;
1191 } 1220 }
1192 1221
1193 SeriesUidMap seriesUidMap; 1222 SeriesUidMap seriesUidMap;
1194 Removals removals; 1223 Removals removals;
1195 Replacements replacements; 1224 Replacements replacements;
1196 1225 bool removePrivateTags;
1197 if (ParseModifyRequest(removals, replacements, call)) 1226
1227 if (ParseModifyRequest(removals, replacements, removePrivateTags, call))
1198 { 1228 {
1199 std::string newStudyId; 1229 std::string newStudyId;
1200 replacements[DICOM_TAG_STUDY_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study); 1230 replacements[DICOM_TAG_STUDY_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study);
1201 1231
1202 for (Instances::const_iterator it = instances.begin(); 1232 for (Instances::const_iterator it = instances.begin();
1222 { 1252 {
1223 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = it2->second; 1253 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = it2->second;
1224 } 1254 }
1225 1255
1226 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); 1256 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone());
1227 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent); 1257 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent, removePrivateTags);
1228 1258
1229 std::string modifiedInstance; 1259 std::string modifiedInstance;
1230 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success) 1260 if (context.Store(modifiedInstance, modified->GetDicom()) != StoreStatus_Success)
1231 { 1261 {
1232 LOG(ERROR) << "Error while storing a modified instance " << *it; 1262 LOG(ERROR) << "Error while storing a modified instance " << *it;