Mercurial > hg > orthanc
changeset 5036:877bc3b96476
Handle Dicom sequences in ExtraMainDicomTags and save them in the 'MainDicomSequences' metadata
line wrap: on
line diff
--- a/NEWS Wed Jun 22 15:37:08 2022 +0200 +++ b/NEWS Fri Jun 24 15:47:10 2022 +0200 @@ -9,6 +9,10 @@ * Lua: new "SetHttpTimeout" function * Lua: new "OnHeartBeat" callback called at regular interval provided that you have configured "LuaHeartBeatPeriod" > 0. +* "ExtraMainDicomTags" configuration now accepts Dicom Sequences. Sequences are + stored in a dedicated new metadata "MainDicomSequences". This should improve + DicomWeb QIDO-RS and avoid warnings like "Accessing Dicom tags from storage when + accessing series : 0040,0275" Maintenance @@ -26,6 +30,7 @@ * API version upgraded to 18 * /system is now reporting "DatabaseServerIdentifier" * Added an Asynchronous mode to /modalities/../move. +* "RequestedTags" option can now include DICOM sequences. Plugins -------
--- a/OrthancFramework/Sources/DicomFormat/DicomMap.cpp Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancFramework/Sources/DicomFormat/DicomMap.cpp Fri Jun 24 15:47:10 2022 +0200 @@ -34,7 +34,7 @@ #include "../OrthancException.h" #include "../Toolbox.h" #include "DicomArray.h" - +#include "../DicomParsing/FromDcmtkBridge.h" namespace Orthanc { @@ -612,6 +612,13 @@ } } + void DicomMap::RemoveTags(const std::set<DicomTag>& tags) + { + for (std::set<DicomTag>::const_iterator it = tags.begin(); it != tags.end(); ++it) + { + Remove(*it); + } + } static void SetupFindTemplate(DicomMap& result, const std::map<DicomTag, std::string>& mainDicomTags) @@ -1522,7 +1529,20 @@ return true; } - + + void DicomMap::ExtractSequences(std::set<DicomTag>& sequences, const std::set<DicomTag>& tags) + { + sequences.clear(); + + for (std::set<DicomTag>::const_iterator it = tags.begin(); it != tags.end(); ++it) + { + ValueRepresentation vr = FromDcmtkBridge::LookupValueRepresentation(*it); + if (vr == ValueRepresentation_Sequence) + { + sequences.insert(*it); + } + } + } void DicomMap::Serialize(Json::Value& target) const {
--- a/OrthancFramework/Sources/DicomFormat/DicomMap.h Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancFramework/Sources/DicomFormat/DicomMap.h Fri Jun 24 15:47:10 2022 +0200 @@ -110,6 +110,8 @@ void Remove(const DicomTag& tag); + void RemoveTags(const std::set<DicomTag>& tags); + void ExtractPatientInformation(DicomMap& result) const; void ExtractStudyInformation(DicomMap& result) const; @@ -147,6 +149,8 @@ static bool HasComputedTags(const std::set<DicomTag>& tags); + static void ExtractSequences(std::set<DicomTag>& sequences, const std::set<DicomTag>& tags); + static const std::set<DicomTag>& GetMainDicomTags(ResourceType level); // returns a string uniquely identifying the list of main dicom tags for a level
--- a/OrthancFramework/UnitTestsSources/DicomMapTests.cpp Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancFramework/UnitTestsSources/DicomMapTests.cpp Fri Jun 24 15:47:10 2022 +0200 @@ -169,6 +169,27 @@ } +TEST(DicomMap, ExtractSequences) +{ + std::set<DicomTag> allTags; + std::set<DicomTag> sequences; + + // empty list + DicomMap::ExtractSequences(sequences, allTags); + ASSERT_EQ(0u, sequences.size()); + + // one tag, no sequence + allTags.insert(DICOM_TAG_PATIENT_NAME); + DicomMap::ExtractSequences(sequences, allTags); + ASSERT_EQ(0u, sequences.size()); + + // one sequence + allTags.insert(DICOM_TAG_REFERENCED_IMAGE_SEQUENCE); + DicomMap::ExtractSequences(sequences, allTags); + ASSERT_EQ(1u, sequences.size()); + ASSERT_TRUE(sequences.find(DICOM_TAG_REFERENCED_IMAGE_SEQUENCE) != sequences.end()); +} + TEST(DicomMap, Tags) { std::set<DicomTag> s;
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Fri Jun 24 15:47:10 2022 +0200 @@ -3402,7 +3402,8 @@ case _OrthancPluginService_GetInstanceSimplifiedJson: { Json::Value dicomAsJson; - instance.GetDicomAsJson(dicomAsJson); + std::set<DicomTag> ignoreTagLength; + instance.GetDicomAsJson(dicomAsJson, ignoreTagLength); std::string s; if (service == _OrthancPluginService_GetInstanceJson)
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Fri Jun 24 15:47:10 2022 +0200 @@ -45,6 +45,51 @@ namespace Orthanc { + // copy all tags from Json + void DicomSequencesMap::FromJson(const Json::Value& value) + { + Json::Value::Members members = value.getMemberNames(); + for (size_t i = 0; i < members.size(); i++) + { + DicomTag tag = FromDcmtkBridge::ParseTag(members[i].c_str()); + sequences_[tag] = value[members[i]]; + } + } + + // copy a subset of tags from Json + void DicomSequencesMap::FromDicomAsJson(const Json::Value& dicomAsJson, const std::set<DicomTag>& tags) + { + for (std::set<DicomTag>::const_iterator it = tags.begin(); + it != tags.end(); ++it) + { + std::string tag = it->Format(); + if (dicomAsJson.isMember(tag)) + { + sequences_[*it] = dicomAsJson[tag]; + } + } + } + + void DicomSequencesMap::ToJson(Json::Value& target, DicomToJsonFormat format) const + { + // add the sequences to "target" + for (std::map<DicomTag, Json::Value>::const_iterator it = sequences_.begin(); + it != sequences_.end(); ++it) + { + Json::Value sequenceForConversion = Json::objectValue; + sequenceForConversion[it->first.Format()] = it->second; + + Json::Value requestedFormatJson; + Toolbox::SimplifyDicomAsJson(requestedFormatJson, sequenceForConversion, format); + + Json::Value::Members keys = requestedFormatJson.getMemberNames(); + for (size_t i = 0; i < keys.size(); i++) // there should always be only one member in this JSON + { + target[keys[i]] = requestedFormatJson[keys[i]]; + } + } + } + namespace { /** @@ -873,6 +918,17 @@ // read all tags from DB transaction.GetMainDicomTags(target.tags_, internalId); + // read all main sequences from DB + std::string serializedSequences; + if (LookupStringMetadata(serializedSequences, target.metadata_, MetadataType_MainDicomSequences)) + { + Json::Value jsonMetadata; + Toolbox::ReadJson(jsonMetadata, serializedSequences); + + assert(jsonMetadata["Version"].asInt() == 1); + target.sequences_.FromJson(jsonMetadata["Sequences"]); + } + // check if we have access to all requestedTags or if we must get tags from parents const std::set<DicomTag>& requestedTags = tuple.get<4>(); @@ -882,7 +938,7 @@ FromDcmtkBridge::ParseListOfTags(savedMainDicomTags, target.mainDicomTagsSignature_); - // read parent main dicom tags as long as we don't have gathered all requested tags + // read parent main dicom tags as long as we have not gathered all requested tags ResourceType currentLevel = target.type_; int64_t currentInternalId = internalId; Toolbox::GetMissingsFromSet(target.missingRequestedTags_, requestedTags, savedMainDicomTags); @@ -2841,6 +2897,7 @@ StoreStatus StatelessDatabaseOperations::Store(std::map<MetadataType, std::string>& instanceMetadata, const DicomMap& dicomSummary, + const std::map<DicomTag, Json::Value>& sequencesToStore, const Attachments& attachments, const MetadataMap& metadata, const DicomInstanceOrigin& origin, @@ -2859,6 +2916,7 @@ StoreStatus storeStatus_; std::map<MetadataType, std::string>& instanceMetadata_; const DicomMap& dicomSummary_; + const std::map<DicomTag, Json::Value>& sequencesToStore_; const Attachments& attachments_; const MetadataMap& metadata_; const DicomInstanceOrigin& origin_; @@ -2890,6 +2948,44 @@ instanceMetadata[metadata] = value; } + static void SetMainDicomSequenceMetadata(ResourcesContent& content, + int64_t resource, + const std::map<DicomTag, Json::Value>& sequencesToStore, // all sequences for all levels ! + ResourceType level) + { + if (sequencesToStore.size() > 0) + { + const std::set<DicomTag>& levelTags = DicomMap::GetMainDicomTags(level); + std::set<DicomTag> levelSequences; + DicomMap::ExtractSequences(levelSequences, levelTags); + + if (levelSequences.size() == 0) + { + return; + } + + Json::Value jsonMetadata; + jsonMetadata["Version"] = 1; + Json::Value jsonSequences = Json::objectValue; + + for (std::set<DicomTag>::const_iterator it = levelSequences.begin(); + it != levelSequences.end(); ++it) + { + std::map<DicomTag, Json::Value>::const_iterator foundSeq = sequencesToStore.find(*it); + if (foundSeq != sequencesToStore.end()) + { + jsonSequences[it->Format()] = foundSeq->second; + } + } + jsonMetadata["Sequences"] = jsonSequences; + + std::string serialized; + Toolbox::WriteFastJson(serialized, jsonMetadata); + + content.AddMetadata(resource, MetadataType_MainDicomSequences, serialized); + } + + } static bool ComputeExpectedNumberOfInstances(int64_t& target, const DicomMap& dicomSummary) @@ -2948,6 +3044,7 @@ public: Operations(std::map<MetadataType, std::string>& instanceMetadata, const DicomMap& dicomSummary, + const std::map<DicomTag, Json::Value>& sequencesToStore, const Attachments& attachments, const MetadataMap& metadata, const DicomInstanceOrigin& origin, @@ -2962,6 +3059,7 @@ storeStatus_(StoreStatus_Failure), instanceMetadata_(instanceMetadata), dicomSummary_(dicomSummary), + sequencesToStore_(sequencesToStore), attachments_(attachments), metadata_(metadata), origin_(origin), @@ -3112,23 +3210,27 @@ content.AddResource(instanceId, ResourceType_Instance, dicomSummary_); SetInstanceMetadata(content, instanceMetadata_, instanceId, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Instance)); // New in Orthanc 1.11.0 + SetMainDicomSequenceMetadata(content, instanceId, sequencesToStore_, ResourceType_Instance); // new in Orthanc 1.11.1 if (status.isNewSeries_) { content.AddResource(status.seriesId_, ResourceType_Series, dicomSummary_); content.AddMetadata(status.seriesId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Series)); // New in Orthanc 1.11.0 + SetMainDicomSequenceMetadata(content, status.seriesId_, sequencesToStore_, ResourceType_Series); // new in Orthanc 1.11.1 } if (status.isNewStudy_) { content.AddResource(status.studyId_, ResourceType_Study, dicomSummary_); content.AddMetadata(status.studyId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Study)); // New in Orthanc 1.11.0 + SetMainDicomSequenceMetadata(content, status.studyId_, sequencesToStore_, ResourceType_Study); // new in Orthanc 1.11.1 } if (status.isNewPatient_) { content.AddResource(status.patientId_, ResourceType_Patient, dicomSummary_); content.AddMetadata(status.patientId_, MetadataType_MainDicomTagsSignature, DicomMap::GetMainDicomTagsSignature(ResourceType_Patient)); // New in Orthanc 1.11.0 + SetMainDicomSequenceMetadata(content, status.patientId_, sequencesToStore_, ResourceType_Patient); // new in Orthanc 1.11.1 } // Attach the auto-computed metadata for the patient/study/series levels @@ -3273,7 +3375,7 @@ }; - Operations operations(instanceMetadata, dicomSummary, attachments, metadata, origin, + Operations operations(instanceMetadata, dicomSummary, sequencesToStore, attachments, metadata, origin, overwrite, hasTransferSyntax, transferSyntax, hasPixelDataOffset, pixelDataOffset, maximumStorageSize, maximumPatients, isReconstruct); Apply(operations);
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Fri Jun 24 15:47:10 2022 +0200 @@ -37,10 +37,25 @@ class ParsedDicomFile; struct ServerIndexChange; + /* + * contains a map of dicom sequences where: + * the key is a DicomTag + * the sequence is serialized in Json "full" format + */ + struct DicomSequencesMap : public boost::noncopyable + { + std::map<DicomTag, Json::Value> sequences_; + + void FromJson(const Json::Value& serialized); + void FromDicomAsJson(const Json::Value& dicomAsJson, const std::set<DicomTag>& tags); + void ToJson(Json::Value& target, DicomToJsonFormat format) const; + }; + struct ExpandedResource : public boost::noncopyable { std::string id_; - DicomMap tags_; // all tags from DB + DicomMap tags_; // all tags from DB (only leaf tags, not sequences !) + DicomSequencesMap sequences_; // the requested sequences std::string mainDicomTagsSignature_; std::string parentId_; std::list<std::string> childrenIds_; @@ -650,6 +665,7 @@ StoreStatus Store(std::map<MetadataType, std::string>& instanceMetadata, const DicomMap& dicomSummary, + const std::map<DicomTag, Json::Value>& sequencesToStore, const Attachments& attachments, const MetadataMap& metadata, const DicomInstanceOrigin& origin,
--- a/OrthancServer/Sources/DicomInstanceToStore.cpp Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancServer/Sources/DicomInstanceToStore.cpp Fri Jun 24 15:47:10 2022 +0200 @@ -186,9 +186,9 @@ OrthancConfiguration::DefaultExtractDicomSummary(summary, dataset_); } - virtual void GetDicomAsJson(Json::Value& dicomAsJson) const ORTHANC_OVERRIDE + virtual void GetDicomAsJson(Json::Value& dicomAsJson, const std::set<DicomTag>& ignoreTagLength) const ORTHANC_OVERRIDE { - OrthancConfiguration::DefaultDicomDatasetToJson(dicomAsJson, dataset_); + OrthancConfiguration::DefaultDicomDatasetToJson(dicomAsJson, dataset_, ignoreTagLength); } virtual void DatasetToJson(Json::Value& target, @@ -275,9 +275,9 @@ } - void DicomInstanceToStore::GetDicomAsJson(Json::Value& dicomAsJson) const + void DicomInstanceToStore::GetDicomAsJson(Json::Value& dicomAsJson, const std::set<DicomTag>& ignoreTagLength) const { - OrthancConfiguration::DefaultDicomDatasetToJson(dicomAsJson, GetParsedDicomFile()); + OrthancConfiguration::DefaultDicomDatasetToJson(dicomAsJson, GetParsedDicomFile(), ignoreTagLength); }
--- a/OrthancServer/Sources/DicomInstanceToStore.h Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancServer/Sources/DicomInstanceToStore.h Fri Jun 24 15:47:10 2022 +0200 @@ -108,7 +108,8 @@ virtual void GetSummary(DicomMap& summary) const; - virtual void GetDicomAsJson(Json::Value& dicomAsJson) const; + virtual void GetDicomAsJson(Json::Value& dicomAsJson, + const std::set<DicomTag>& ignoreTagLength) const; virtual void DatasetToJson(Json::Value& target, DicomToJsonFormat format,
--- a/OrthancServer/Sources/OrthancConfiguration.cpp Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancServer/Sources/OrthancConfiguration.cpp Fri Jun 24 15:47:10 2022 +0200 @@ -1126,9 +1126,9 @@ void OrthancConfiguration::DefaultDicomDatasetToJson(Json::Value& target, - DcmDataset& dicom) + DcmDataset& dicom, + const std::set<DicomTag>& ignoreTagLength) { - std::set<DicomTag> ignoreTagLength; FromDcmtkBridge::ExtractDicomAsJson(target, dicom, DicomToJsonFormat_Full, DicomToJsonFlags_Default, ORTHANC_MAXIMUM_TAG_LENGTH, ignoreTagLength); }
--- a/OrthancServer/Sources/OrthancConfiguration.h Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancServer/Sources/OrthancConfiguration.h Fri Jun 24 15:47:10 2022 +0200 @@ -263,7 +263,8 @@ const ParsedDicomFile& dicom); static void DefaultDicomDatasetToJson(Json::Value& target, - DcmDataset& dicom); + DcmDataset& dicom, + const std::set<DicomTag>& ignoreTagLength); static void DefaultDicomDatasetToJson(Json::Value& target, const ParsedDicomFile& dicom,
--- a/OrthancServer/Sources/OrthancInitialization.cpp Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancServer/Sources/OrthancInitialization.cpp Fri Jun 24 15:47:10 2022 +0200 @@ -262,13 +262,13 @@ ValueRepresentation vr = FromDcmtkBridge::LookupValueRepresentation(tag); if (vr == ValueRepresentation_Sequence) { - LOG(WARNING) << " - " << tagName << " can not be added in the Extra Main Dicom Tags since it is a sequence"; + LOG(INFO) << " - " << tagName << " (sequence)"; } else { - DicomMap::AddMainDicomTag(tag, tagName, level); LOG(INFO) << " - " << tagName; } + DicomMap::AddMainDicomTag(tag, tagName, level); } } }
--- a/OrthancServer/Sources/ServerContext.cpp Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancServer/Sources/ServerContext.cpp Fri Jun 24 15:47:10 2022 +0200 @@ -526,7 +526,12 @@ bool hasTransferSyntax = dicom.LookupTransferSyntax(transferSyntax); DicomMap summary; - dicom.GetSummary(summary); + dicom.GetSummary(summary); // -> this includes only the leaf nodes + + std::set<DicomTag> allMainDicomTags = DicomMap::GetAllMainDicomTags(); + std::set<DicomTag> mainDicomSequences; + DicomMap::ExtractSequences(mainDicomSequences, allMainDicomTags); + std::map<DicomTag, Json::Value> sequencesToStore; try { @@ -536,9 +541,19 @@ DicomInstanceHasher hasher(summary); resultPublicId = hasher.HashInstance(); - Json::Value dicomAsJson; - dicom.GetDicomAsJson(dicomAsJson); + Json::Value dicomAsJson; // -> this includes the sequences + + dicom.GetDicomAsJson(dicomAsJson, mainDicomSequences /*ignoreTagLength*/); // make sure that sequences that we wish to store in DB are not 'cropped' + for (std::set<DicomTag>::const_iterator it = mainDicomSequences.begin(); + it != mainDicomSequences.end(); ++it) + { + if (dicomAsJson.isMember(it->Format())) + { + sequencesToStore[*it] = dicomAsJson[it->Format()]; + } + } + Json::Value simplifiedTags; Toolbox::SimplifyDicomAsJson(simplifiedTags, dicomAsJson, DicomToJsonFormat_Human); @@ -616,7 +631,7 @@ typedef std::map<MetadataType, std::string> InstanceMetadata; InstanceMetadata instanceMetadata; result.SetStatus(index_.Store( - instanceMetadata, summary, attachments, dicom.GetMetadata(), dicom.GetOrigin(), overwrite, + instanceMetadata, summary, sequencesToStore, attachments, dicom.GetMetadata(), dicom.GetOrigin(), overwrite, hasTransferSyntax, transferSyntax, hasPixelDataOffset, pixelDataOffset, isReconstruct)); // Only keep the metadata for the "instance" level @@ -2094,6 +2109,9 @@ target[REQUESTED_TAGS] = Json::objectValue; FromDcmtkBridge::ToJson(target[REQUESTED_TAGS], tags, format); + + // add the sequences to the requested tags + resource.sequences_.ToJson(target[REQUESTED_TAGS], format); } } @@ -2405,6 +2423,9 @@ // possibly merge missing requested tags from dicom-as-json if (!resource.missingRequestedTags_.empty() && !DicomMap::HasOnlyComputedTags(resource.missingRequestedTags_)) { + std::set<DicomTag> missingSequences; + DicomMap::ExtractSequences(missingSequences, resource.missingRequestedTags_); + OrthancConfiguration::ReaderLock lock; if (lock.GetConfiguration().IsWarningEnabled(Warnings_001_TagsBeingReadFromStorage)) { @@ -2449,12 +2470,14 @@ } Json::Value tmpDicomAsJson; - ReadDicomAsJson(tmpDicomAsJson, instanceId_); + ReadDicomAsJson(tmpDicomAsJson, instanceId_, resource.missingRequestedTags_ /* ignoreTagLength */); // read all tags from DICOM and avoid cropping requested tags tagsFromJson.FromDicomAsJson(tmpDicomAsJson); + resource.sequences_.FromDicomAsJson(tmpDicomAsJson, missingSequences); } else { tagsFromJson.FromDicomAsJson(*dicomAsJson); + resource.sequences_.FromDicomAsJson(*dicomAsJson, missingSequences); } resource.tags_.Merge(tagsFromJson);
--- a/OrthancServer/Sources/ServerEnumerations.cpp Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancServer/Sources/ServerEnumerations.cpp Fri Jun 24 15:47:10 2022 +0200 @@ -61,6 +61,7 @@ dictMetadataType_.Add(MetadataType_Instance_HttpUsername, "HttpUsername"); dictMetadataType_.Add(MetadataType_Instance_PixelDataOffset, "PixelDataOffset"); dictMetadataType_.Add(MetadataType_MainDicomTagsSignature, "MainDicomTagsSignature"); + dictMetadataType_.Add(MetadataType_MainDicomSequences, "MainDicomSequences"); dictContentType_.Add(FileContentType_Dicom, "dicom"); dictContentType_.Add(FileContentType_DicomAsJson, "dicom-as-json");
--- a/OrthancServer/Sources/ServerEnumerations.h Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancServer/Sources/ServerEnumerations.h Fri Jun 24 15:47:10 2022 +0200 @@ -152,6 +152,7 @@ MetadataType_Instance_HttpUsername = 13, // New in Orthanc 1.4.0 MetadataType_Instance_PixelDataOffset = 14, // New in Orthanc 1.9.0 MetadataType_MainDicomTagsSignature = 15, // New in Orthanc 1.11.0 + MetadataType_MainDicomSequences = 16, // New in Orthanc 1.11.1 // Make sure that the value "65535" can be stored into this enumeration MetadataType_StartUser = 1024,
--- a/OrthancServer/Sources/ServerIndex.cpp Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancServer/Sources/ServerIndex.cpp Fri Jun 24 15:47:10 2022 +0200 @@ -511,6 +511,7 @@ StoreStatus ServerIndex::Store(std::map<MetadataType, std::string>& instanceMetadata, const DicomMap& dicomSummary, + const std::map<DicomTag, Json::Value>& sequencesToStore, const ServerIndex::Attachments& attachments, const ServerIndex::MetadataMap& metadata, const DicomInstanceOrigin& origin, @@ -531,7 +532,7 @@ } return StatelessDatabaseOperations::Store( - instanceMetadata, dicomSummary, attachments, metadata, origin, overwrite, hasTransferSyntax, + instanceMetadata, dicomSummary, sequencesToStore, attachments, metadata, origin, overwrite, hasTransferSyntax, transferSyntax, hasPixelDataOffset, pixelDataOffset, maximumStorageSize, maximumPatients, isReconstruct); }
--- a/OrthancServer/Sources/ServerIndex.h Wed Jun 22 15:37:08 2022 +0200 +++ b/OrthancServer/Sources/ServerIndex.h Fri Jun 24 15:47:10 2022 +0200 @@ -77,6 +77,7 @@ StoreStatus Store(std::map<MetadataType, std::string>& instanceMetadata, const DicomMap& dicomSummary, + const std::map<DicomTag, Json::Value>& sequencesToStore, const Attachments& attachments, const MetadataMap& metadata, const DicomInstanceOrigin& origin,
--- a/TODO Wed Jun 22 15:37:08 2022 +0200 +++ b/TODO Fri Jun 24 15:47:10 2022 +0200 @@ -39,7 +39,7 @@ * Add configurations to enable/disable warnings: - Modifying an instance while keeping its original SOPInstanceUID: This should be avoided! - Modifying a study while keeping its original StudyInstanceUID: This should be avoided! -* Allow storing sequences in DB to speed up Dicom-web: https://groups.google.com/g/orthanc-users/c/6CTlfa8UGM4/m/V1D0xuKQAAAJ + ============================ Documentation (Orthanc Book)