Mercurial > hg > orthanc
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 |