Mercurial > hg > orthanc
diff OrthancServer/Sources/ResourceFinder.cpp @ 5665:d8c86698110c find-refactoring
implemented computed tag: Instance Availability
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 04 Jul 2024 14:36:24 +0200 |
parents | 3f13db27b399 |
children | aa231c18b9d2 |
line wrap: on
line diff
--- a/OrthancServer/Sources/ResourceFinder.cpp Thu Jul 04 11:59:50 2024 +0200 +++ b/OrthancServer/Sources/ResourceFinder.cpp Thu Jul 04 14:36:24 2024 +0200 @@ -421,6 +421,8 @@ request_.GetParentRetrieveSpecification(ResourceType_Study).SetRetrieveMetadata(true); requestedStudyTags_.insert(tag); } + + hasRequestedTags_ = true; } else if (DicomMap::IsMainDicomTag(tag, ResourceType_Study)) { @@ -437,6 +439,8 @@ request_.GetParentRetrieveSpecification(ResourceType_Study).SetRetrieveMetadata(true); requestedStudyTags_.insert(tag); } + + hasRequestedTags_ = true; } else if (DicomMap::IsMainDicomTag(tag, ResourceType_Series)) { @@ -454,6 +458,8 @@ request_.GetParentRetrieveSpecification(ResourceType_Series).SetRetrieveMetadata(true); requestedSeriesTags_.insert(tag); } + + hasRequestedTags_ = true; } else if (DicomMap::IsMainDicomTag(tag, ResourceType_Instance)) { @@ -473,19 +479,36 @@ assert(request_.IsRetrieveMetadata()); requestedInstanceTags_.insert(tag); } + + hasRequestedTags_ = true; + } + else if (tag == DICOM_TAG_INSTANCE_AVAILABILITY) + { + requestedComputedTags_.insert(tag); + hasRequestedTags_ = true; + } + else if (tag == DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES) + { + if (request_.GetLevel() == ResourceType_Series) + { + requestedComputedTags_.insert(tag); + hasRequestedTags_ = true; + request_.GetChildrenRetrieveSpecification(ResourceType_Instance).SetRetrieveCount(true); + } } else { - // This is not a main DICOM tag: We will be forced to access the DICOM file anyway + // This is neither a main DICOM tag, nor a computed DICOM tag: + // We will be forced to access the DICOM file anyway requestedTagsFromFileStorage_.insert(tag); if (request_.GetLevel() != ResourceType_Instance) { request_.SetRetrieveOneInstanceIdentifier(true); } + + hasRequestedTags_ = true; } - - hasRequestedTags_ = true; } @@ -498,6 +521,111 @@ } + void ResourceFinder::InjectComputedTags(DicomMap& requestedTags, + const FindResponse::Resource& resource) const + { + switch (resource.GetLevel()) + { + case ResourceType_Patient: + break; + + case ResourceType_Study: + break; + + case ResourceType_Series: + if (IsRequestedComputedTag(DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES)) + { + requestedTags.SetValue(DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES, + boost::lexical_cast<std::string>(resource.GetChildrenIdentifiers().size()), false); + } + break; + + case ResourceType_Instance: + if (IsRequestedComputedTag(DICOM_TAG_INSTANCE_AVAILABILITY)) + { + requestedTags.SetValue(DICOM_TAG_INSTANCE_AVAILABILITY, "ONLINE", false); + } + break; + + default: + throw OrthancException(ErrorCode_InternalError); + } + } + + + static void ReadMissingTagsFromStorageArea(DicomMap& requestedTags, + ServerContext& context, + const FindRequest& request, + const FindResponse::Resource& resource, + const std::set<DicomTag>& missingTags) + { + OrthancConfiguration::ReaderLock lock; + if (lock.GetConfiguration().IsWarningEnabled(Warnings_001_TagsBeingReadFromStorage)) + { + std::string missings; + FromDcmtkBridge::FormatListOfTags(missings, missingTags); + + LOG(WARNING) << "W001: Accessing Dicom tags from storage when accessing " + << Orthanc::GetResourceTypeText(resource.GetLevel(), false, false) + << ": " << missings; + } + + std::string instancePublicId; + + if (request.IsRetrieveOneInstanceIdentifier()) + { + instancePublicId = resource.GetOneInstanceIdentifier(); + } + else if (request.GetLevel() == ResourceType_Instance) + { + instancePublicId = resource.GetIdentifier(); + } + else + { + FindRequest requestDicomAttachment(request.GetLevel()); + requestDicomAttachment.SetOrthancId(request.GetLevel(), resource.GetIdentifier()); + requestDicomAttachment.SetRetrieveOneInstanceIdentifier(true); + + FindResponse responseDicomAttachment; + context.GetIndex().ExecuteFind(responseDicomAttachment, requestDicomAttachment); + + if (responseDicomAttachment.GetSize() != 1 || + !responseDicomAttachment.GetResourceByIndex(0).HasOneInstanceIdentifier()) + { + throw OrthancException(ErrorCode_InexistentFile); + } + else + { + instancePublicId = responseDicomAttachment.GetResourceByIndex(0).GetOneInstanceIdentifier(); + } + } + + LOG(INFO) << "Will retrieve missing DICOM tags from instance: " << instancePublicId; + + // TODO-FIND: What do we do if the DICOM has been removed since the request? + // Do we fail, or do we skip the resource? + + Json::Value tmpDicomAsJson; + context.ReadDicomAsJson(tmpDicomAsJson, instancePublicId, missingTags /* ignoreTagLength */); + + DicomMap tmpDicomMap; + tmpDicomMap.FromDicomAsJson(tmpDicomAsJson, false /* append */, true /* parseSequences*/); + + for (std::set<DicomTag>::const_iterator it = missingTags.begin(); it != missingTags.end(); ++it) + { + assert(!requestedTags.HasTag(*it)); + if (tmpDicomMap.HasTag(*it)) + { + requestedTags.SetValue(*it, tmpDicomMap.GetValue(*it)); + } + else + { + requestedTags.SetNullValue(*it); // TODO-FIND: Is this compatible with Orthanc <= 1.12.3? + } + } + } + + void ResourceFinder::Execute(Json::Value& target, ServerContext& context) const { @@ -521,90 +649,30 @@ Json::Value item; Expand(item, resource, context.GetIndex()); - std::set<DicomTag> missingTags = requestedTagsFromFileStorage_; - - DicomMap requestedTags; - InjectRequestedTags(requestedTags, missingTags, resource, ResourceType_Patient, requestedPatientTags_); - InjectRequestedTags(requestedTags, missingTags, resource, ResourceType_Study, requestedStudyTags_); - InjectRequestedTags(requestedTags, missingTags, resource, ResourceType_Series, requestedSeriesTags_); - InjectRequestedTags(requestedTags, missingTags, resource, ResourceType_Instance, requestedInstanceTags_); - - if (!missingTags.empty()) + if (hasRequestedTags_) { - if (!allowStorageAccess_) - { - throw OrthancException(ErrorCode_BadSequenceOfCalls, - "Cannot add missing requested tags, as access to file storage is disallowed"); - } - - OrthancConfiguration::ReaderLock lock; - if (lock.GetConfiguration().IsWarningEnabled(Warnings_001_TagsBeingReadFromStorage)) - { - std::string missings; - FromDcmtkBridge::FormatListOfTags(missings, missingTags); + DicomMap requestedTags; + InjectComputedTags(requestedTags, resource); - LOG(WARNING) << "W001: Accessing Dicom tags from storage when accessing " - << Orthanc::GetResourceTypeText(resource.GetLevel(), false, false) - << ": " << missings; - } + std::set<DicomTag> missingTags = requestedTagsFromFileStorage_; + InjectRequestedTags(requestedTags, missingTags, resource, ResourceType_Patient, requestedPatientTags_); + InjectRequestedTags(requestedTags, missingTags, resource, ResourceType_Study, requestedStudyTags_); + InjectRequestedTags(requestedTags, missingTags, resource, ResourceType_Series, requestedSeriesTags_); + InjectRequestedTags(requestedTags, missingTags, resource, ResourceType_Instance, requestedInstanceTags_); - std::string instancePublicId; - - if (request_.IsRetrieveOneInstanceIdentifier()) - { - instancePublicId = resource.GetOneInstanceIdentifier(); - } - else if (request_.GetLevel() == ResourceType_Instance) + if (!missingTags.empty()) { - instancePublicId = resource.GetIdentifier(); - } - else - { - FindRequest requestDicomAttachment(request_.GetLevel()); - requestDicomAttachment.SetOrthancId(request_.GetLevel(), resource.GetIdentifier()); - requestDicomAttachment.SetRetrieveOneInstanceIdentifier(true); - - FindResponse responseDicomAttachment; - context.GetIndex().ExecuteFind(responseDicomAttachment, requestDicomAttachment); - - if (responseDicomAttachment.GetSize() != 1 || - !responseDicomAttachment.GetResourceByIndex(0).HasOneInstanceIdentifier()) + if (!allowStorageAccess_) { - throw OrthancException(ErrorCode_InexistentFile); + throw OrthancException(ErrorCode_BadSequenceOfCalls, + "Cannot add missing requested tags, as access to file storage is disallowed"); } else { - instancePublicId = responseDicomAttachment.GetResourceByIndex(0).GetOneInstanceIdentifier(); + ReadMissingTagsFromStorageArea(requestedTags, context, request_, resource, missingTags); } } - LOG(INFO) << "Will retrieve missing DICOM tags from instance: " << instancePublicId; - - // TODO-FIND: What do we do if the DICOM has been removed since the request? - // Do we fail, or do we skip the resource? - - Json::Value tmpDicomAsJson; - context.ReadDicomAsJson(tmpDicomAsJson, instancePublicId, missingTags /* ignoreTagLength */); - - DicomMap tmpDicomMap; - tmpDicomMap.FromDicomAsJson(tmpDicomAsJson, false /* append */, true /* parseSequences*/); - - for (std::set<DicomTag>::const_iterator it = missingTags.begin(); it != missingTags.end(); ++it) - { - assert(!requestedTags.HasTag(*it)); - if (tmpDicomMap.HasTag(*it)) - { - requestedTags.SetValue(*it, tmpDicomMap.GetValue(*it)); - } - else - { - requestedTags.SetNullValue(*it); // TODO-FIND: Is this compatible with Orthanc <= 1.12.3? - } - } - } - - if (hasRequestedTags_) - { static const char* const REQUESTED_TAGS = "RequestedTags"; item[REQUESTED_TAGS] = Json::objectValue; FromDcmtkBridge::ToJson(item[REQUESTED_TAGS], requestedTags, format_);