comparison OrthancServer/OrthancRestApi.cpp @ 310:6ab6cdeedf4e

global sequences
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 21 Dec 2012 11:18:27 +0100
parents fbf2b2282086
children 26efccdff583
comparison
equal deleted inserted replaced
309:ee97f0923ddd 310:6ab6cdeedf4e
839 839
840 840
841 841
842 // Modification of DICOM instances ------------------------------------------ 842 // Modification of DICOM instances ------------------------------------------
843 843
844 typedef std::set<DicomTag> Removals;
845 typedef std::map<DicomTag, std::string> Replacements;
846
844 static void ReplaceInstanceInternal(ParsedDicomFile& toModify, 847 static void ReplaceInstanceInternal(ParsedDicomFile& toModify,
845 const Json::Value& removals, 848 const Removals& removals,
846 const Json::Value& replacements, 849 const Replacements& replacements,
847 DicomReplaceMode mode) 850 DicomReplaceMode mode)
848 { 851 {
849 if (!replacements.isObject() || 852 for (Removals::const_iterator it = removals.begin();
850 !removals.isArray()) 853 it != removals.end(); it++)
851 { 854 {
852 throw OrthancException(ErrorCode_BadRequest); 855 toModify.Remove(*it);
853 } 856 }
854 857
855 for (Json::Value::ArrayIndex i = 0; i < removals.size(); i++) 858 for (Replacements::const_iterator it = replacements.begin();
856 { 859 it != replacements.end(); it++)
857 DicomTag tag = FromDcmtkBridge::ParseTag(removals[i].asString()); 860 {
858 toModify.Remove(tag); 861 toModify.Replace(it->first, it->second, mode);
859 }
860
861 Json::Value::Members members = replacements.getMemberNames();
862 for (size_t i = 0; i < members.size(); i++)
863 {
864 const std::string& name = members[i];
865 std::string value = replacements[name].asString();
866
867 DicomTag tag = FromDcmtkBridge::ParseTag(name);
868 toModify.Replace(tag, value, mode);
869 } 862 }
870 863
871 // A new SOP instance UID is automatically generated 864 // A new SOP instance UID is automatically generated
872 std::string instanceUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Instance); 865 std::string instanceUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Instance);
873 toModify.Replace(DICOM_TAG_SOP_INSTANCE_UID, instanceUid, DicomReplaceMode_InsertIfAbsent); 866 toModify.Replace(DICOM_TAG_SOP_INSTANCE_UID, instanceUid, DicomReplaceMode_InsertIfAbsent);
874 } 867 }
875 868
876 869
877 static bool ParseModifyRequest(Json::Value& removals, 870 static void ParseRemovals(Removals& target,
878 Json::Value& replacements, 871 const Json::Value& removals)
872 {
873 if (!removals.isArray())
874 {
875 throw OrthancException(ErrorCode_BadRequest);
876 }
877
878 target.clear();
879
880 for (Json::Value::ArrayIndex i = 0; i < removals.size(); i++)
881 {
882 DicomTag tag = FromDcmtkBridge::ParseTag(removals[i].asString());
883 target.insert(tag);
884 }
885 }
886
887
888 static void ParseReplacements(Replacements& target,
889 const Json::Value& replacements)
890 {
891 if (!replacements.isObject())
892 {
893 throw OrthancException(ErrorCode_BadRequest);
894 }
895
896 target.clear();
897
898 Json::Value::Members members = replacements.getMemberNames();
899 for (size_t i = 0; i < members.size(); i++)
900 {
901 const std::string& name = members[i];
902 std::string value = replacements[name].asString();
903
904 DicomTag tag = FromDcmtkBridge::ParseTag(name);
905 target[tag] = value;
906 }
907 }
908
909
910 static void SetupAnonymization(Removals& removals,
911 Replacements& replacements)
912 {
913 removals.clear();
914 replacements.clear();
915
916 // This is table X.1-1 from DICOM supplement 55: Attribute Level Confidentiality
917 removals.insert(DicomTag(0x0008, 0x0014)); // Instance Creator UID
918 // 0008-0018 - SOP Instance UID is automatically set by ReplaceInstanceInternal()
919 removals.insert(DicomTag(0x0008, 0x0050)); // Accession number
920 /* removals.insert(DicomTag(0x0008, 0x )); //
921 removals.insert(DicomTag(0x , 0x )); //
922 removals.insert(DicomTag(0x , 0x )); //
923 removals.insert(DicomTag(0x , 0x )); //
924 removals.insert(DicomTag(0x , 0x )); //
925 removals.insert(DicomTag(0x , 0x )); //
926 removals.insert(DicomTag(0x , 0x )); //
927 removals.insert(DicomTag(0x , 0x )); //
928 removals.insert(DicomTag(0x , 0x )); //
929 removals.insert(DicomTag(0x , 0x )); //
930 removals.insert(DicomTag(0x , 0x )); //
931 removals.insert(DicomTag(0x , 0x )); //
932 removals.insert(DicomTag(0x , 0x )); //
933 removals.insert(DicomTag(0x , 0x )); //
934 removals.insert(DicomTag(0x , 0x )); //
935 removals.insert(DicomTag(0x , 0x )); //
936 removals.insert(DicomTag(0x , 0x )); //
937 removals.insert(DicomTag(0x , 0x )); //
938 */
939 }
940
941
942 static bool ParseModifyRequest(Removals& removals,
943 Replacements& replacements,
879 const RestApi::PostCall& call) 944 const RestApi::PostCall& call)
880 { 945 {
881 Json::Value request; 946 Json::Value request;
882 if (call.ParseJsonRequest(request) && 947 if (call.ParseJsonRequest(request) &&
883 request.isObject()) 948 request.isObject())
884 { 949 {
885 removals = Json::arrayValue; 950 Json::Value removalsPart = Json::arrayValue;
886 replacements = Json::objectValue; 951 Json::Value replacementsPart = Json::objectValue;
887 952
888 if (request.isMember("Remove")) 953 if (request.isMember("Remove"))
889 { 954 {
890 removals = request["Remove"]; 955 removalsPart = request["Remove"];
891 } 956 }
892 957
893 if (request.isMember("Replace")) 958 if (request.isMember("Replace"))
894 { 959 {
895 replacements = request["Replace"]; 960 replacementsPart = request["Replace"];
896 } 961 }
962
963 ParseRemovals(removals, removalsPart);
964 ParseReplacements(replacements, replacementsPart);
897 965
898 return true; 966 return true;
899 } 967 }
900 else 968 else
901 { 969 {
909 RETRIEVE_CONTEXT(call); 977 RETRIEVE_CONTEXT(call);
910 978
911 std::string id = call.GetUriComponent("id", ""); 979 std::string id = call.GetUriComponent("id", "");
912 ParsedDicomFile& dicom = context.GetDicomFile(id); 980 ParsedDicomFile& dicom = context.GetDicomFile(id);
913 981
914 Json::Value removals, replacements; 982 Removals removals;
983 Replacements replacements;
984
915 if (ParseModifyRequest(removals, replacements, call)) 985 if (ParseModifyRequest(removals, replacements, call))
916 { 986 {
917 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); 987 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone());
918 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent); 988 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent);
919 context.GetIndex().SetMetadata(id, MetadataType_ModifiedFrom, id); 989 context.GetIndex().SetMetadata(id, MetadataType_ModifiedFrom, id);
934 if (instances.size() == 0) 1004 if (instances.size() == 0)
935 { 1005 {
936 return; 1006 return;
937 } 1007 }
938 1008
939 Json::Value removals, replacements; 1009 Removals removals;
1010 Replacements replacements;
1011
940 if (ParseModifyRequest(removals, replacements, call)) 1012 if (ParseModifyRequest(removals, replacements, call))
941 { 1013 {
942 std::string newSeriesId; 1014 std::string newSeriesId;
943 replacements["0020-000e"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); 1015 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series);
944 1016
945 for (Instances::const_iterator it = instances.begin(); 1017 for (Instances::const_iterator it = instances.begin();
946 it != instances.end(); it++) 1018 it != instances.end(); it++)
947 { 1019 {
948 LOG(INFO) << "Modifying instance " << *it; 1020 LOG(INFO) << "Modifying instance " << *it;
988 { 1060 {
989 return; 1061 return;
990 } 1062 }
991 1063
992 SeriesUidMap seriesUidMap; 1064 SeriesUidMap seriesUidMap;
993 1065 Removals removals;
994 Json::Value removals, replacements; 1066 Replacements replacements;
1067
995 if (ParseModifyRequest(removals, replacements, call)) 1068 if (ParseModifyRequest(removals, replacements, call))
996 { 1069 {
997 std::string newStudyId; 1070 std::string newStudyId;
998 replacements["0020-000d"] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study); 1071 replacements[DICOM_TAG_STUDY_INSTANCE_UID] = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Study);
999 1072
1000 for (Instances::const_iterator it = instances.begin(); 1073 for (Instances::const_iterator it = instances.begin();
1001 it != instances.end(); it++) 1074 it != instances.end(); it++)
1002 { 1075 {
1003 LOG(INFO) << "Modifying instance " << *it; 1076 LOG(INFO) << "Modifying instance " << *it;
1012 SeriesUidMap::const_iterator it2 = seriesUidMap.find(seriesId); 1085 SeriesUidMap::const_iterator it2 = seriesUidMap.find(seriesId);
1013 if (it2 == seriesUidMap.end()) 1086 if (it2 == seriesUidMap.end())
1014 { 1087 {
1015 std::string newSeriesUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series); 1088 std::string newSeriesUid = FromDcmtkBridge::GenerateUniqueIdentifier(DicomRootLevel_Series);
1016 seriesUidMap[seriesId] = newSeriesUid; 1089 seriesUidMap[seriesId] = newSeriesUid;
1017 replacements["0020-000e"] = newSeriesUid; 1090 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = newSeriesUid;
1018 } 1091 }
1019 else 1092 else
1020 { 1093 {
1021 replacements["0020-000e"] = it2->second; 1094 replacements[DICOM_TAG_SERIES_INSTANCE_UID] = it2->second;
1022 } 1095 }
1023 1096
1024 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone()); 1097 std::auto_ptr<ParsedDicomFile> modified(dicom.Clone());
1025 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent); 1098 ReplaceInstanceInternal(*modified, removals, replacements, DicomReplaceMode_InsertIfAbsent);
1026 1099