changeset 681:3bdb5db8e839 query-retrieve

generalization of query/retrieve
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 24 Jan 2014 17:40:45 +0100
parents 28e4b3ec8aff
children 67e6400fca03
files Core/DicomFormat/DicomMap.cpp Core/DicomFormat/DicomMap.h Core/DicomFormat/DicomTag.h OrthancServer/DicomProtocol/DicomUserConnection.cpp OrthancServer/OrthancFindRequestHandler.cpp OrthancServer/ServerIndex.cpp OrthancServer/ServerIndex.h OrthancServer/main.cpp
diffstat 8 files changed, 258 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/Core/DicomFormat/DicomMap.cpp	Fri Jan 24 15:35:39 2014 +0100
+++ b/Core/DicomFormat/DicomMap.cpp	Fri Jan 24 17:40:45 2014 +0100
@@ -386,4 +386,32 @@
     GetMainDicomTagsInternal(result, ResourceType_Series);
     GetMainDicomTagsInternal(result, ResourceType_Instance);
   }
+
+
+  void DicomMap::ExtractMainDicomTagsForLevel(DicomMap& result,
+                                              ResourceType level) const
+  {
+    switch (level)
+    {
+      case ResourceType_Patient:
+        ExtractPatientInformation(result);
+        break;
+
+      case ResourceType_Study:
+        ExtractStudyInformation(result);
+        break;
+
+      case ResourceType_Series:
+        ExtractSeriesInformation(result);
+        break;
+
+      case ResourceType_Instance:
+        ExtractInstanceInformation(result);
+        break;
+
+      default:
+        throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+  }
+
 }
--- a/Core/DicomFormat/DicomMap.h	Fri Jan 24 15:35:39 2014 +0100
+++ b/Core/DicomFormat/DicomMap.h	Fri Jan 24 17:40:45 2014 +0100
@@ -160,5 +160,8 @@
     static void GetMainDicomTags(std::set<DicomTag>& result, ResourceType level);
 
     static void GetMainDicomTags(std::set<DicomTag>& result);
+
+    void ExtractMainDicomTagsForLevel(DicomMap& result,
+                                      ResourceType level) const;
   };
 }
--- a/Core/DicomFormat/DicomTag.h	Fri Jan 24 15:35:39 2014 +0100
+++ b/Core/DicomFormat/DicomTag.h	Fri Jan 24 17:40:45 2014 +0100
@@ -90,6 +90,8 @@
   static const DicomTag DICOM_TAG_SERIES_INSTANCE_UID(0x0020, 0x000e);
   static const DicomTag DICOM_TAG_STUDY_INSTANCE_UID(0x0020, 0x000d);
   static const DicomTag DICOM_TAG_PIXEL_DATA(0x7fe0, 0x0010);
+  static const DicomTag DICOM_TAG_STUDY_DESCRIPTION(0x0008, 0x1030);
+  static const DicomTag DICOM_TAG_SERIES_DESCRIPTION(0x0008, 0x103e);
 
   static const DicomTag DICOM_TAG_IMAGE_INDEX(0x0054, 0x1330);
   static const DicomTag DICOM_TAG_INSTANCE_NUMBER(0x0020, 0x0013);
--- a/OrthancServer/DicomProtocol/DicomUserConnection.cpp	Fri Jan 24 15:35:39 2014 +0100
+++ b/OrthancServer/DicomProtocol/DicomUserConnection.cpp	Fri Jan 24 17:40:45 2014 +0100
@@ -340,12 +340,10 @@
         // This is a particular case for ClearCanvas, thanks to Peter Somlo <peter.somlo@gmail.com>.
         // https://groups.google.com/d/msg/orthanc-users/j-6C3MAVwiw/iolB9hclom8J
         // http://www.clearcanvas.ca/Home/Community/OldForums/tabid/526/aff/11/aft/14670/afv/topic/Default.aspx
-        printf("CLEAR CANVAS\n");
         DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "IMAGE");
       }
       else
       {
-        printf("GENERIC\n");
         DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "INSTANCE");
       }
 
--- a/OrthancServer/OrthancFindRequestHandler.cpp	Fri Jan 24 15:35:39 2014 +0100
+++ b/OrthancServer/OrthancFindRequestHandler.cpp	Fri Jan 24 17:40:45 2014 +0100
@@ -311,12 +311,142 @@
   }
 
 
+  static bool LookupCandidateResourcesInternal(/* inout */ std::set<std::string>& resources,
+                                               /* in */  bool alreadyFiltered,
+                                               /* in */  ServerIndex& index,
+                                               /* in */  ResourceType level,
+                                               /* in */  const DicomMap& query,
+                                               /* in */  DicomTag tag)
+  {
+    assert(alreadyFiltered || resources.size() == 0);
+
+    if (!query.HasTag(tag))
+    {
+      return alreadyFiltered;
+    }
+
+    const DicomValue& value = query.GetValue(tag);
+    if (value.IsNull())
+    {
+      return alreadyFiltered;
+    }
+
+    std::string str = query.GetValue(tag).AsString();
+    if (IsWildcard(str))
+    {
+      return alreadyFiltered;
+    }
+
+    std::list<std::string> matches;
+    index.LookupTagValue(matches, tag, str/*, level*/);
+
+    if (alreadyFiltered)
+    {
+      std::set<std::string> previous = resources;
+      
+      for (std::list<std::string>::const_iterator 
+             it = matches.begin(); it != matches.end(); it++)
+      {
+        if (previous.find(*it) != previous.end())
+        {
+          resources.insert(*it);
+        }
+      }
+    }
+    else
+    {
+      for (std::list<std::string>::const_iterator 
+             it = matches.begin(); it != matches.end(); it++)
+      {
+        resources.insert(*it);
+      }
+    }
+
+    return true;
+  }
+
+
+  static bool LookupCandidateResourcesAtOneLevel(/* out */ std::set<std::string>& resources,
+                                                 /* in */  ServerIndex& index,
+                                                 /* in */  ResourceType level,
+                                                 /* in */  const DicomMap& fullQuery,
+                                                 /* in */  ModalityManufacturer manufacturer)
+  {
+    DicomMap tmp;
+    fullQuery.ExtractMainDicomTagsForLevel(tmp, level);
+    DicomArray query(tmp);
+
+    if (query.GetSize() == 0)
+    {
+      return false;
+    }
+
+    for (size_t i = 0; i < query.GetSize(); i++)
+    {
+      const DicomTag tag = query.GetElement(i).GetTag();
+      const DicomValue& value = query.GetElement(i).GetValue();
+      if (!value.IsNull())
+      {
+        // TODO TODO TODO
+      }
+    }
+
+    printf(">>>>>>>>>>\n");
+    query.Print(stdout); 
+    printf("<<<<<<<<<<\n\n");
+    return true;
+  }
+
+
   static void LookupCandidateResources(/* out */ std::list<std::string>& resources,
                                        /* in */  ServerIndex& index,
                                        /* in */  ResourceType level,
                                        /* in */  const DicomMap& query,
                                        /* in */  ModalityManufacturer manufacturer)
   {
+#if 1
+    {
+      std::set<std::string> s;
+      LookupCandidateResourcesAtOneLevel(s, index, ResourceType_Patient, query, manufacturer);
+      LookupCandidateResourcesAtOneLevel(s, index, ResourceType_Study, query, manufacturer);
+      LookupCandidateResourcesAtOneLevel(s, index, ResourceType_Series, query, manufacturer);
+      LookupCandidateResourcesAtOneLevel(s, index, ResourceType_Instance, query, manufacturer);
+    }
+
+    std::set<std::string> filtered;
+    bool isFiltered = false; 
+
+    // Filter by indexed tags, from most specific to least specific
+    //isFiltered = LookupCandidateResourcesInternal(filtered, isFiltered, index, level, query, DICOM_TAG_SOP_INSTANCE_UID);
+    isFiltered = LookupCandidateResourcesInternal(filtered, isFiltered, index, level, query, DICOM_TAG_SERIES_INSTANCE_UID);
+    //isFiltered = LookupCandidateResourcesInternal(filtered, isFiltered, index, level, query, DICOM_TAG_STUDY_INSTANCE_UID);
+    //isFiltered = LookupCandidateResourcesInternal(filtered, isFiltered, index, level, query, DICOM_TAG_PATIENT_ID);
+
+    resources.clear();
+
+    if (isFiltered)
+    {
+      for (std::set<std::string>::const_iterator
+             it = filtered.begin(); it != filtered.end(); it++)
+      {
+        resources.push_back(*it);
+      }
+    }
+    else
+    {
+      // No indexed tag matches the query. Return all the resources at this query level.
+      Json::Value allResources;
+      index.GetAllUuids(allResources, level);
+      assert(allResources.type() == Json::arrayValue);
+
+      for (Json::Value::ArrayIndex i = 0; i < allResources.size(); i++)
+      {
+        resources.push_back(allResources[i].asString());
+      }
+    }
+
+#else
+
     // TODO : Speed up using full querying against the MainDicomTags.
 
     resources.clear();
@@ -371,6 +501,7 @@
         resources.push_back(allResources[i].asString());
       }
     }
+#endif
   }
 
 
@@ -416,7 +547,8 @@
       default:
         if (level != ResourceType_Patient &&
             level != ResourceType_Study &&
-            level != ResourceType_Series)
+            level != ResourceType_Series &&
+            level != ResourceType_Instance)
         {
           throw OrthancException(ErrorCode_NotImplemented);
         }
@@ -456,6 +588,8 @@
      **/
 
     DicomArray query(input);
+    query.Print(stdout);
+
     for (std::list<std::string>::const_iterator 
            resource = resources.begin(); resource != resources.end(); ++resource)
     {
--- a/OrthancServer/ServerIndex.cpp	Fri Jan 24 15:35:39 2014 +0100
+++ b/OrthancServer/ServerIndex.cpp	Fri Jan 24 17:40:45 2014 +0100
@@ -1575,4 +1575,55 @@
       result.push_back(db_->GetPublicId(*it));
     }
   }
+
+
+  // TODO IS IT USEFUL???
+  void ServerIndex::LookupTagValue(std::set<std::string>& result,
+                                   DicomTag tag,
+                                   const std::string& value,
+                                   ResourceType type)
+  {
+    std::list<std::string> lst;
+    LookupTagValue(lst, tag, value, type);
+
+    result.clear();
+    for (std::list<std::string>::const_iterator
+           it = lst.begin(); it != lst.end(); it++)
+    {
+      result.insert(*it);
+    }
+  }
+
+
+  // TODO IS IT USEFUL???
+  void ServerIndex::LookupTagValue(std::set<std::string>& result,
+                                   DicomTag tag,
+                                   const std::string& value)
+  {
+    std::list<std::string> lst;
+    LookupTagValue(lst, tag, value);
+
+    result.clear();
+    for (std::list<std::string>::const_iterator
+           it = lst.begin(); it != lst.end(); it++)
+    {
+      result.insert(*it);
+    }
+  }
+
+
+  // TODO IS IT USEFUL???
+  void ServerIndex::LookupTagValue(std::set<std::string>& result,
+                                   const std::string& value)
+  {
+    std::list<std::string> lst;
+    LookupTagValue(lst, value);
+
+    result.clear();
+    for (std::list<std::string>::const_iterator
+           it = lst.begin(); it != lst.end(); it++)
+    {
+      result.insert(*it);
+    }
+  }
 }
--- a/OrthancServer/ServerIndex.h	Fri Jan 24 15:35:39 2014 +0100
+++ b/OrthancServer/ServerIndex.h	Fri Jan 24 17:40:45 2014 +0100
@@ -213,5 +213,21 @@
 
     void LookupTagValue(std::list<std::string>& result,
                         const std::string& value);
+
+
+    // TODO IS IT USEFUL???
+    void LookupTagValue(std::set<std::string>& result,
+                        DicomTag tag,
+                        const std::string& value,
+                        ResourceType type);
+
+    // TODO IS IT USEFUL???
+    void LookupTagValue(std::set<std::string>& result,
+                        DicomTag tag,
+                        const std::string& value);
+
+    // TODO IS IT USEFUL???
+    void LookupTagValue(std::set<std::string>& result,
+                        const std::string& value);
   };
 }
--- a/OrthancServer/main.cpp	Fri Jan 24 15:35:39 2014 +0100
+++ b/OrthancServer/main.cpp	Fri Jan 24 17:40:45 2014 +0100
@@ -412,6 +412,29 @@
       httpServer.Start();
       dicomServer.Start();
 
+
+      {
+        DicomUserConnection c;
+        c.SetLocalApplicationEntityTitle("ORTHANC");
+        c.SetDistantApplicationEntityTitle("ORTHANC");
+        c.SetDistantHost("localhost");
+        c.SetDistantPort(4343);
+        c.Open();
+
+        DicomMap m; // Delphine
+        m.SetValue(DICOM_TAG_PATIENT_ID, "5423962");
+        m.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "1.2.840.113845.11.1000000001951524609.20121203131451.1457891");
+        m.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "1.2.840.113619.2.278.3.262930758.589.1354512768.115");
+        m.SetValue(DICOM_TAG_SOP_INSTANCE_UID, "1.3.12.2.1107.5.2.33.37097.2012041613043195815872177");
+
+        DicomFindAnswers fnd;
+        c.FindInstance(fnd, m);
+        //c.FindSeries(fnd, m);
+
+        printf("ok %d\n", fnd.GetSize());
+      }
+
+
       LOG(WARNING) << "Orthanc has started";
       Toolbox::ServerBarrier();