Mercurial > hg > orthanc
diff OrthancServer/OrthancFindRequestHandler.cpp @ 3015:abe49ca61cd5
On C-FIND, avoid accessing the storage area whenever possible
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 14 Dec 2018 12:10:03 +0100 |
parents | af1530b45290 |
children | 2cbafb5d5a62 |
line wrap: on
line diff
--- a/OrthancServer/OrthancFindRequestHandler.cpp Thu Dec 13 17:58:27 2018 +0100 +++ b/OrthancServer/OrthancFindRequestHandler.cpp Fri Dec 14 12:10:03 2018 +0100 @@ -89,82 +89,6 @@ } - static void ExtractTagFromMainDicomTags(std::set<std::string>& target, - ServerIndex& index, - const DicomTag& tag, - const std::list<std::string>& resources, - ResourceType level) - { - for (std::list<std::string>::const_iterator - it = resources.begin(); it != resources.end(); ++it) - { - DicomMap tags; - if (index.GetMainDicomTags(tags, *it, level, level) && - tags.HasTag(tag)) - { - target.insert(tags.GetValue(tag).GetContent()); - } - } - } - - - static bool ExtractMetadata(std::set<std::string>& target, - ServerIndex& index, - MetadataType metadata, - const std::list<std::string>& resources) - { - for (std::list<std::string>::const_iterator - it = resources.begin(); it != resources.end(); ++it) - { - std::string value; - if (index.LookupMetadata(value, *it, metadata)) - { - target.insert(value); - } - else - { - // This metadata is unavailable for some resource, give up - return false; - } - } - - return true; - } - - - static void ExtractTagFromInstancesOnDisk(std::set<std::string>& target, - ServerContext& context, - const DicomTag& tag, - const std::list<std::string>& instances) - { - // WARNING: This function is slow, as it reads the JSON file - // summarizing each instance of interest from the hard drive. - - std::string formatted = tag.Format(); - - for (std::list<std::string>::const_iterator - it = instances.begin(); it != instances.end(); ++it) - { - Json::Value dicom; - context.ReadDicomAsJson(dicom, *it); - - if (dicom.isMember(formatted)) - { - const Json::Value& source = dicom[formatted]; - - if (source.type() == Json::objectValue && - source.isMember("Type") && - source.isMember("Value") && - source["Type"].asString() == "String" && - source["Value"].type() == Json::stringValue) - { - target.insert(source["Value"].asString()); - } - } - } - } - - static void ComputePatientCounters(DicomMap& result, ServerIndex& index, const std::string& patient, @@ -230,7 +154,24 @@ if (query.HasTag(DICOM_TAG_MODALITIES_IN_STUDY)) { std::set<std::string> values; - ExtractTagFromMainDicomTags(values, index, DICOM_TAG_MODALITY, series, ResourceType_Series); + + for (std::list<std::string>::const_iterator + it = series.begin(); it != series.end(); ++it) + { + DicomMap tags; + if (index.GetMainDicomTags(tags, *it, ResourceType_Series, ResourceType_Series)) + { + const DicomValue* value = tags.TestAndGetValue(DICOM_TAG_MODALITY); + + if (value != NULL && + !value->IsNull() && + !value->IsBinary()) + { + values.insert(value->GetContent()); + } + } + } + StoreSetOfStrings(result, DICOM_TAG_MODALITIES_IN_STUDY, values); } @@ -253,27 +194,17 @@ { std::set<std::string> values; - if (ExtractMetadata(values, index, MetadataType_Instance_SopClassUid, instances)) - { - // The metadata "SopClassUid" is available for each of these instances - StoreSetOfStrings(result, DICOM_TAG_SOP_CLASSES_IN_STUDY, values); - } - else + for (std::list<std::string>::const_iterator + it = instances.begin(); it != instances.end(); ++it) { - OrthancConfiguration::ReaderLock lock; - - if (lock.GetConfiguration().GetBooleanParameter("AllowFindSopClassesInStudy", false)) + std::string value; + if (context.LookupOrReconstructMetadata(value, *it, MetadataType_Instance_SopClassUid)) { - ExtractTagFromInstancesOnDisk(values, context, DICOM_TAG_SOP_CLASS_UID, instances); - StoreSetOfStrings(result, DICOM_TAG_SOP_CLASSES_IN_STUDY, values); - } - else - { - result.SetValue(DICOM_TAG_SOP_CLASSES_IN_STUDY, "", false); - LOG(WARNING) << "The handling of \"SOP Classes in Study\" (0008,0062) " - << "in C-FIND requests is disabled"; + values.insert(value); } } + + StoreSetOfStrings(result, DICOM_TAG_SOP_CLASSES_IN_STUDY, values); } } @@ -366,11 +297,22 @@ static void AddAnswer(DicomFindAnswers& answers, const DicomMap& mainDicomTags, - const Json::Value* dicomAsJson, // only used for sequences + const Json::Value* dicomAsJson, const DicomArray& query, const std::list<DicomTag>& sequencesToReturn, const DicomMap* counters) { + DicomMap match; + + if (dicomAsJson != NULL) + { + match.FromDicomAsJson(*dicomAsJson); + } + else + { + match.Assign(mainDicomTags); + } + DicomMap result; for (size_t i = 0; i < query.GetSize(); i++) @@ -384,26 +326,22 @@ { // Do not include the encoding, this is handled by class ParsedDicomFile } - else if (dicomAsJson != NULL) + else { - std::string tag = query.GetElement(i).GetTag().Format(); - std::string value; - if (dicomAsJson->isMember(tag)) + const DicomTag& tag = query.GetElement(i).GetTag(); + const DicomValue* value = match.TestAndGetValue(tag); + + if (value != NULL && + !value->IsNull() && + !value->IsBinary()) { - value = dicomAsJson->get(tag, Json::arrayValue).get("Value", "").asString(); - result.SetValue(query.GetElement(i).GetTag(), value, false); + result.SetValue(tag, value->GetContent(), false); } else { - result.SetValue(query.GetElement(i).GetTag(), "", false); + result.SetValue(tag, "", false); } } - else - { - // Best-effort - // TODO - throw OrthancException(ErrorCode_NotImplemented); - } } if (counters != NULL) @@ -420,11 +358,15 @@ { LOG(WARNING) << "The C-FIND request does not return any DICOM tag"; } - else if (sequencesToReturn.empty() || - dicomAsJson == NULL) + else if (sequencesToReturn.empty()) { answers.Add(result); } + else if (dicomAsJson == NULL) + { + LOG(WARNING) << "C-FIND query requesting a sequence, but reading JSON from disk is disabled"; + answers.Add(result); + } else { ParsedDicomFile dicom(result); @@ -536,48 +478,50 @@ DicomFindAnswers& answers_; ServerContext& context_; ResourceType level_; - const DicomMap& filteredInput_; + const DicomMap& query_; + DicomArray queryAsArray_; const std::list<DicomTag>& sequencesToReturn_; - DicomArray query_; public: LookupVisitor(DicomFindAnswers& answers, ServerContext& context, ResourceType level, - const DicomMap& filteredInput, + const DicomMap& query, const std::list<DicomTag>& sequencesToReturn) : answers_(answers), context_(context), level_(level), - filteredInput_(filteredInput), - sequencesToReturn_(sequencesToReturn), - query_(filteredInput) + query_(query), + queryAsArray_(query), + sequencesToReturn_(sequencesToReturn) { answers_.SetComplete(false); } virtual bool IsDicomAsJsonNeeded() const { -#if 1 - return true; - -#else - // TODO - // Ask the "DICOM-as-JSON" attachment only if sequences are to // be returned OR if "query_" contains non-main DICOM tags! - // TODO - configuration option - bool findFromDatabase; + DicomMap withoutSpecialTags; + withoutSpecialTags.Assign(query_); + + // Check out "ComputeCounters()" + withoutSpecialTags.Remove(DICOM_TAG_MODALITIES_IN_STUDY); + withoutSpecialTags.Remove(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_INSTANCES); + withoutSpecialTags.Remove(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_SERIES); + withoutSpecialTags.Remove(DICOM_TAG_NUMBER_OF_PATIENT_RELATED_STUDIES); + withoutSpecialTags.Remove(DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES); + withoutSpecialTags.Remove(DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES); + withoutSpecialTags.Remove(DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES); + withoutSpecialTags.Remove(DICOM_TAG_SOP_CLASSES_IN_STUDY); + + // Check out "AddAnswer()" + withoutSpecialTags.Remove(DICOM_TAG_SPECIFIC_CHARACTER_SET); + withoutSpecialTags.Remove(DICOM_TAG_QUERY_RETRIEVE_LEVEL); - { - // New configuration option in 1.5.1 - OrthancConfiguration::ReaderLock lock; - findFromDatabase = lock.GetConfiguration().GetUnsignedIntegerParameter("FindFromDatabase", false); - } - - return !sequencesToReturn_.empty(); -#endif + return (!sequencesToReturn_.empty() || + !withoutSpecialTags.HasOnlyMainDicomTags()); } virtual void MarkAsComplete() @@ -590,8 +534,10 @@ const DicomMap& mainDicomTags, const Json::Value* dicomAsJson) { - std::auto_ptr<DicomMap> counters(ComputeCounters(context_, instanceId, level_, filteredInput_)); - AddAnswer(answers_, mainDicomTags, dicomAsJson, query_, sequencesToReturn_, counters.get()); + std::auto_ptr<DicomMap> counters(ComputeCounters(context_, instanceId, level_, query_)); + + AddAnswer(answers_, mainDicomTags, dicomAsJson, + queryAsArray_, sequencesToReturn_, counters.get()); } };