changeset 5043:ec5c203a97ea

returning sequences in MainDicomTags and RequestedTags
author Alain Mazy <am@osimis.io>
date Mon, 27 Jun 2022 15:22:19 +0200
parents 120945ce48b6
children 6fed78e13233
files NEWS OrthancFramework/Resources/CMake/OrthancFrameworkConfiguration.cmake OrthancFramework/Sources/DicomFormat/DicomSequencesMap.cpp OrthancFramework/Sources/DicomFormat/DicomSequencesMap.h OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp OrthancServer/Sources/Database/StatelessDatabaseOperations.h OrthancServer/Sources/ServerContext.cpp
diffstat 7 files changed, 173 insertions(+), 93 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Mon Jun 27 14:09:17 2022 +0200
+++ b/NEWS	Mon Jun 27 15:22:19 2022 +0200
@@ -12,7 +12,8 @@
 * "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"
+  accessing series : 0040,0275".
+  Main dicom sequences can now be returned in "MainDicomTags" and in "RequestedTags".
 
 
 Maintenance
--- a/OrthancFramework/Resources/CMake/OrthancFrameworkConfiguration.cmake	Mon Jun 27 14:09:17 2022 +0200
+++ b/OrthancFramework/Resources/CMake/OrthancFrameworkConfiguration.cmake	Mon Jun 27 15:22:19 2022 +0200
@@ -197,6 +197,7 @@
     ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomFormat/DicomInstanceHasher.cpp
     ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomFormat/DicomIntegerPixelAccessor.cpp
     ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomFormat/DicomMap.cpp
+    ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomFormat/DicomSequencesMap.cpp
     ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomFormat/DicomStreamReader.cpp
     ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomFormat/DicomValue.cpp
     ${CMAKE_CURRENT_LIST_DIR}/../../Sources/DicomFormat/StreamBlockReader.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancFramework/Sources/DicomFormat/DicomSequencesMap.cpp	Mon Jun 27 15:22:19 2022 +0200
@@ -0,0 +1,100 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2022 Osimis S.A., Belgium
+ * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "../PrecompiledHeaders.h"
+#include "DicomSequencesMap.h"
+#include "../Toolbox.h"
+
+namespace Orthanc
+{
+
+#if ORTHANC_ENABLE_DCMTK == 1
+
+  // copy all tags from Json (used to read from metadata)
+  void DicomSequencesMap::Deserialize(const Json::Value& serialized)
+  {
+    Json::Value::Members members = serialized.getMemberNames();
+    for (size_t i = 0; i < members.size(); i++)
+    {
+      DicomTag tag(0, 0);
+      if (DicomTag::ParseHexadecimal(tag, members[i].c_str()))
+      {
+        sequences_[tag] = serialized[members[i]];
+      }
+    }
+  }
+
+#endif
+
+  // serialize a subet of tags (used to store in the metadata)
+  void DicomSequencesMap::Serialize(Json::Value& target, const std::set<DicomTag>& tags) const
+  {
+    // add the sequences to "target"
+    for (std::map<DicomTag, Json::Value>::const_iterator it = sequences_.begin();
+          it != sequences_.end(); ++it)
+    {
+      if (tags.find(it->first) != tags.end())
+      {
+        target[it->first.Format()] = it->second;
+      }
+    }
+  }
+
+  // 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 std::set<DicomTag>& tags) const
+  {
+    // add the sequences to "target"
+    for (std::map<DicomTag, Json::Value>::const_iterator it = sequences_.begin();
+          it != sequences_.end(); ++it)
+    {
+      Json::Value sequenceFullJson = Json::objectValue;
+      sequenceFullJson[it->first.Format()] = it->second;
+
+      Json::Value& requestedFormatJson = sequenceFullJson;
+      Json::Value convertedJson;
+
+      if (format != DicomToJsonFormat_Full)
+      {
+        Toolbox::SimplifyDicomAsJson(convertedJson, sequenceFullJson, format);
+        requestedFormatJson = convertedJson;
+      }
+      
+      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]];
+      }
+    }
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancFramework/Sources/DicomFormat/DicomSequencesMap.h	Mon Jun 27 15:22:19 2022 +0200
@@ -0,0 +1,57 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2022 Osimis S.A., Belgium
+ * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "../../../OrthancFramework/Sources/DicomFormat/DicomTag.h"
+
+#include <json/value.h>
+#include <boost/noncopyable.hpp>
+
+#include <map>
+
+namespace Orthanc
+{
+  class DatabaseLookup;
+  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 Deserialize(const Json::Value& serialized);
+    void Serialize(Json::Value& target, const std::set<DicomTag>& tagsSubset) const;
+    void FromDicomAsJson(const Json::Value& dicomAsJson, const std::set<DicomTag>& tagsSubset);
+    void ToJson(Json::Value& target, DicomToJsonFormat format, const std::set<DicomTag>& tagsSubset) const;
+
+    size_t GetSize() const
+    {
+      return sequences_.size();
+    }
+  };
+}
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp	Mon Jun 27 14:09:17 2022 +0200
+++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp	Mon Jun 27 15:22:19 2022 +0200
@@ -45,71 +45,6 @@
 
 namespace Orthanc
 {
-  // copy all tags from Json (used to read from metadata)
-  void DicomSequencesMap::Deserialize(const Json::Value& serialized)
-  {
-    Json::Value::Members members = serialized.getMemberNames();
-    for (size_t i = 0; i < members.size(); i++)
-    {
-      DicomTag tag = FromDcmtkBridge::ParseTag(members[i].c_str());
-      sequences_[tag] = serialized[members[i]];
-    }
-  }
-
-  // serialize a subet of tags (used to store in the metadata)
-  void DicomSequencesMap::Serialize(Json::Value& target, const std::set<DicomTag>& tags) const
-  {
-    // add the sequences to "target"
-    for (std::map<DicomTag, Json::Value>::const_iterator it = sequences_.begin();
-          it != sequences_.end(); ++it)
-    {
-      if (tags.find(it->first) != tags.end())
-      {
-        target[it->first.Format()] = it->second;
-      }
-    }
-  }
-
-  // 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 = sequenceForConversion;
-      Json::Value convertedJson;
-
-      if (format != DicomToJsonFormat_Full)
-      {
-        Toolbox::SimplifyDicomAsJson(convertedJson, sequenceForConversion, format);
-        requestedFormatJson = convertedJson;
-      }
-      
-      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
   {
     /**
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.h	Mon Jun 27 14:09:17 2022 +0200
+++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.h	Mon Jun 27 15:22:19 2022 +0200
@@ -23,6 +23,7 @@
 #pragma once
 
 #include "../../../OrthancFramework/Sources/DicomFormat/DicomMap.h"
+#include "../../../OrthancFramework/Sources/DicomFormat/DicomSequencesMap.h"
 
 #include "IDatabaseWrapper.h"
 #include "../DicomInstanceOrigin.h"
@@ -37,31 +38,11 @@
   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 Deserialize(const Json::Value& serialized);
-    void Serialize(Json::Value& target, const std::set<DicomTag>& tags) const;
-    void FromDicomAsJson(const Json::Value& dicomAsJson, const std::set<DicomTag>& tags);
-    void ToJson(Json::Value& target, DicomToJsonFormat format) const;
-
-    size_t GetSize() const
-    {
-      return sequences_.size();
-    }
-  };
-
   struct ExpandedResource : public boost::noncopyable
   {
     std::string                         id_;
     DicomMap                            tags_;          // all tags from DB (only leaf tags, not sequences !)
-    DicomSequencesMap                   sequences_;     // the requested sequences
+    DicomSequencesMap                   sequences_;     // the requested sequences (from MainDicomTags or RequestedTags)
     std::string                         mainDicomTagsSignature_;
     std::string                         parentId_;
     std::list<std::string>              childrenIds_;
--- a/OrthancServer/Sources/ServerContext.cpp	Mon Jun 27 14:09:17 2022 +0200
+++ b/OrthancServer/Sources/ServerContext.cpp	Mon Jun 27 15:22:19 2022 +0200
@@ -2083,10 +2083,11 @@
     target[MAIN_DICOM_TAGS] = Json::objectValue;
     FromDcmtkBridge::ToJson(target[MAIN_DICOM_TAGS], mainDicomTags, format);
     
-    {// TODO add the sequences to the main dicom tags
-      // const std::set<DicomTag>& mainDicomTags = DicomMap::MainDicomTagsConfiguration::GetInstance().GetMainDicomTagsByLevel(resource.type_);
-      // mainDicomTags.
-      // resource.sequences_.ToJson(target[MAIN_DICOM_TAGS], format);
+    {// add the main DICOM sequences to the main dicom tags
+      const std::set<DicomTag>& mainDicomTags = DicomMap::GetMainDicomTags(resource.type_);
+      std::set<DicomTag> mainDicomSequences;
+      DicomMap::ExtractSequences(mainDicomSequences, mainDicomTags);
+      resource.sequences_.ToJson(target[MAIN_DICOM_TAGS], format, mainDicomSequences);
     }
 
     if (resource.type_ == ResourceType_Study)
@@ -2108,8 +2109,12 @@
       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);
+      {// add the requested sequences to the requested tags
+        std::set<DicomTag> requestedDicomSequences;
+        DicomMap::ExtractSequences(requestedDicomSequences, requestedTags);
+        resource.sequences_.ToJson(target[REQUESTED_TAGS], format, requestedDicomSequences);
+      }
+
     }
 
   }