Mercurial > hg > orthanc
comparison OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp @ 4938:f630796a59b1 more-tags
ExpandResource now able to return computed tags (like ModalitiesInStudies)
author | Alain Mazy <am@osimis.io> |
---|---|
date | Mon, 14 Mar 2022 16:44:00 +0100 |
parents | 8422e4f99a18 |
children | e8a2e145c80e |
comparison
equal
deleted
inserted
replaced
4937:3f9b9865c8cc | 4938:f630796a59b1 |
---|---|
758 { | 758 { |
759 return false; | 759 return false; |
760 } | 760 } |
761 } | 761 } |
762 | 762 |
763 static void ComputeSeriesTags(DicomMap& result, | |
764 const std::list<std::string>& children, | |
765 const std::set<DicomTag>& requestedTags) | |
766 { | |
767 if (requestedTags.count(DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES) > 0) | |
768 { | |
769 result.SetValue(DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES, | |
770 boost::lexical_cast<std::string>(children.size()), false); | |
771 } | |
772 } | |
773 | |
774 static void ComputeStudyTags(DicomMap& result, | |
775 ReadOnlyTransaction& transaction, | |
776 const std::string& studyPublicId, | |
777 int64_t studyInternalId, | |
778 const std::set<DicomTag>& requestedTags) | |
779 { | |
780 std::list<int64_t> seriesInternalIds; | |
781 std::list<int64_t> instancesInternalIds; | |
782 | |
783 transaction.GetChildrenInternalId(seriesInternalIds, studyInternalId); | |
784 | |
785 if (requestedTags.count(DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES) > 0) | |
786 { | |
787 result.SetValue(DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES, | |
788 boost::lexical_cast<std::string>(seriesInternalIds.size()), false); | |
789 } | |
790 | |
791 if (requestedTags.count(DICOM_TAG_MODALITIES_IN_STUDY) > 0) | |
792 { | |
793 std::set<std::string> values; | |
794 | |
795 for (std::list<int64_t>::const_iterator | |
796 it = seriesInternalIds.begin(); it != seriesInternalIds.end(); ++it) | |
797 { | |
798 if (requestedTags.count(DICOM_TAG_MODALITIES_IN_STUDY) > 0) | |
799 { | |
800 DicomMap tags; | |
801 transaction.GetMainDicomTags(tags, *it); | |
802 | |
803 const DicomValue* value = tags.TestAndGetValue(DICOM_TAG_MODALITY); | |
804 | |
805 if (value != NULL && | |
806 !value->IsNull() && | |
807 !value->IsBinary()) | |
808 { | |
809 values.insert(value->GetContent()); | |
810 } | |
811 } | |
812 } | |
813 | |
814 std::string modalities; | |
815 Toolbox::JoinStrings(modalities, values, "\\"); | |
816 result.SetValue(DICOM_TAG_MODALITIES_IN_STUDY, modalities, false); | |
817 } | |
818 | |
819 if (requestedTags.count(DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES) > 0 | |
820 || requestedTags.count(DICOM_TAG_SOP_CLASSES_IN_STUDY) > 0) | |
821 { | |
822 for (std::list<int64_t>::const_iterator | |
823 it = seriesInternalIds.begin(); it != seriesInternalIds.end(); ++it) | |
824 { | |
825 std::list<int64_t> seriesInstancesIds; | |
826 transaction.GetChildrenInternalId(seriesInstancesIds, *it); | |
827 | |
828 instancesInternalIds.splice(instancesInternalIds.end(), seriesInstancesIds); | |
829 } | |
830 | |
831 if (requestedTags.count(DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES) > 0) | |
832 { | |
833 result.SetValue(DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES, | |
834 boost::lexical_cast<std::string>(instancesInternalIds.size()), false); | |
835 } | |
836 | |
837 if (requestedTags.count(DICOM_TAG_SOP_CLASSES_IN_STUDY) > 0) | |
838 { | |
839 std::set<std::string> values; | |
840 | |
841 for (std::list<int64_t>::const_iterator | |
842 it = instancesInternalIds.begin(); it != instancesInternalIds.end(); ++it) | |
843 { | |
844 std::map<MetadataType, std::string> instanceMetadata; | |
845 // Extract the metadata | |
846 transaction.GetAllMetadata(instanceMetadata, *it); | |
847 | |
848 std::string value; | |
849 if (!LookupStringMetadata(value, instanceMetadata, MetadataType_Instance_SopClassUid)) | |
850 { | |
851 throw OrthancException(ErrorCode_InternalError, "Unable to get the SOP Class Uid from an instance of the study " + studyPublicId + " because the instance has been saved with an old version of Orthanc (< 1.2.0). You should POST to /studies/" + studyPublicId + "/reconstruct to avoid this error"); | |
852 } | |
853 | |
854 values.insert(value); | |
855 } | |
856 | |
857 std::string sopClassUids; | |
858 Toolbox::JoinStrings(sopClassUids, values, "\\"); | |
859 result.SetValue(DICOM_TAG_SOP_CLASSES_IN_STUDY, sopClassUids, false); | |
860 } | |
861 } | |
862 } | |
863 | |
864 static void ComputePatientTags(DicomMap& result, | |
865 ReadOnlyTransaction& transaction, | |
866 const std::string& patientPublicId, | |
867 int64_t patientInternalId, | |
868 const std::set<DicomTag>& requestedTags) | |
869 { | |
870 std::list<int64_t> studiesInternalIds; | |
871 std::list<int64_t> seriesInternalIds; | |
872 std::list<int64_t> instancesInternalIds; | |
873 | |
874 bool hasNbRelatedStudies = requestedTags.count(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_STUDIES) > 0; | |
875 bool hasNbRelatedSeries = requestedTags.count(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_SERIES) > 0; | |
876 bool hasNbRelatedInstances = requestedTags.count(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_INSTANCES) > 0; | |
877 | |
878 transaction.GetChildrenInternalId(studiesInternalIds, patientInternalId); | |
879 | |
880 if (hasNbRelatedStudies) | |
881 { | |
882 result.SetValue(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_STUDIES, | |
883 boost::lexical_cast<std::string>(studiesInternalIds.size()), false); | |
884 } | |
885 | |
886 if (hasNbRelatedSeries || hasNbRelatedInstances) | |
887 { | |
888 for (std::list<int64_t>::const_iterator | |
889 it = studiesInternalIds.begin(); it != studiesInternalIds.end(); ++it) | |
890 { | |
891 std::list<int64_t> thisSeriesIds; | |
892 transaction.GetChildrenInternalId(thisSeriesIds, *it); | |
893 seriesInternalIds.splice(seriesInternalIds.end(), thisSeriesIds); | |
894 | |
895 if (hasNbRelatedInstances) | |
896 { | |
897 for (std::list<int64_t>::const_iterator | |
898 it2 = seriesInternalIds.begin(); it2 != seriesInternalIds.end(); ++it2) | |
899 { | |
900 std::list<int64_t> thisInstancesIds; | |
901 transaction.GetChildrenInternalId(thisInstancesIds, *it2); | |
902 instancesInternalIds.splice(instancesInternalIds.end(), thisInstancesIds); | |
903 } | |
904 } | |
905 } | |
906 | |
907 if (hasNbRelatedSeries) | |
908 { | |
909 result.SetValue(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_SERIES, | |
910 boost::lexical_cast<std::string>(seriesInternalIds.size()), false); | |
911 } | |
912 | |
913 if (hasNbRelatedInstances) | |
914 { | |
915 result.SetValue(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_INSTANCES, | |
916 boost::lexical_cast<std::string>(instancesInternalIds.size()), false); | |
917 } | |
918 } | |
919 } | |
763 | 920 |
764 public: | 921 public: |
765 virtual void ApplyTuple(ReadOnlyTransaction& transaction, | 922 virtual void ApplyTuple(ReadOnlyTransaction& transaction, |
766 const Tuple& tuple) ORTHANC_OVERRIDE | 923 const Tuple& tuple) ORTHANC_OVERRIDE |
767 { | 924 { |
916 target.tags_.Merge(parentTags); | 1073 target.tags_.Merge(parentTags); |
917 } | 1074 } |
918 | 1075 |
919 currentInternalId = currentParentId; | 1076 currentInternalId = currentParentId; |
920 } | 1077 } |
1078 | |
1079 { // handle the tags that must be rebuilt because they are not saved in DB | |
1080 if (target.type_ == ResourceType_Study && ( | |
1081 target.missingRequestedTags_.count(DICOM_TAG_MODALITIES_IN_STUDY) > 0 | |
1082 || target.missingRequestedTags_.count(DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES) > 0 | |
1083 || target.missingRequestedTags_.count(DICOM_TAG_SOP_CLASSES_IN_STUDY) > 0 | |
1084 || target.missingRequestedTags_.count(DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES) > 0 | |
1085 )) | |
1086 { | |
1087 ComputeStudyTags(target.tags_, transaction, target.id_, internalId, requestedTags); | |
1088 } | |
1089 | |
1090 if (target.type_ == ResourceType_Series | |
1091 && target.missingRequestedTags_.count(DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES) > 0) | |
1092 { | |
1093 ComputeSeriesTags(target.tags_, target.childrenIds_, requestedTags); | |
1094 } | |
1095 | |
1096 if (target.type_ == ResourceType_Patient && ( | |
1097 target.missingRequestedTags_.count(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_STUDIES) > 0 | |
1098 || target.missingRequestedTags_.count(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_SERIES) > 0 | |
1099 || target.missingRequestedTags_.count(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_INSTANCES) > 0 | |
1100 )) | |
1101 { | |
1102 ComputePatientTags(target.tags_, transaction, target.id_, internalId, requestedTags); | |
1103 } | |
1104 } | |
1105 | |
921 } | 1106 } |
922 | 1107 |
923 std::string tmp; | 1108 std::string tmp; |
924 | 1109 |
925 if (LookupStringMetadata(tmp, target.metadata_, MetadataType_AnonymizedFrom)) | 1110 if (LookupStringMetadata(tmp, target.metadata_, MetadataType_AnonymizedFrom)) |