changeset 1796:5e08a5fe6b27 worklists

HierarchicalMatcher - extracting tags
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 19 Nov 2015 18:32:00 +0100
parents af6840eb23ee
children 23722a191e4e
files OrthancServer/Search/HierarchicalMatcher.cpp OrthancServer/Search/HierarchicalMatcher.h OrthancServer/main.cpp
diffstat 3 files changed, 171 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/Search/HierarchicalMatcher.cpp	Thu Nov 19 17:41:22 2015 +0100
+++ b/OrthancServer/Search/HierarchicalMatcher.cpp	Thu Nov 19 18:32:00 2015 +0100
@@ -35,6 +35,7 @@
 
 #include "../../Core/OrthancException.h"
 #include "../FromDcmtkBridge.h"
+#include "../ToDcmtkBridge.h"
 
 #include <dcmtk/dcmdata/dcfilefo.h>
 
@@ -84,6 +85,12 @@
       }
 
       DicomTag tag(FromDcmtkBridge::Convert(element->getTag()));
+      if (tag == DICOM_TAG_SPECIFIC_CHARACTER_SET)
+      {
+        // Ignore this specific tag
+        continue;
+      }
+
       ValueRepresentation vr = FromDcmtkBridge::GetValueRepresentation(tag);
 
       if (constraints_.find(tag) != constraints_.end() ||
@@ -179,4 +186,139 @@
 
     return s;
   }
+
+
+  bool HierarchicalMatcher::Match(ParsedDicomFile& dicom) const
+  {
+    return MatchInternal(*dicom.GetDcmtkObject().getDataset(),
+                         dicom.GetEncoding());
+  }
+
+
+  bool HierarchicalMatcher::MatchInternal(DcmItem& item,
+                                          Encoding encoding) const
+  {
+    for (Constraints::const_iterator it = constraints_.begin();
+         it != constraints_.end(); ++it)
+    {
+      if (it->second != NULL)
+      {
+        DcmTagKey tag = ToDcmtkBridge::Convert(it->first);
+
+        DcmElement* element = NULL;
+        if (!item.findAndGetElement(tag, element).good() ||
+            element == NULL)
+        {
+          return false;
+        }
+
+        std::auto_ptr<DicomValue> value(FromDcmtkBridge::ConvertLeafElement
+                                        (*element, DicomToJsonFlags_None, encoding));
+
+        if (value->IsNull() ||
+            value->IsBinary() ||
+            !it->second->Match(value->GetContent()))
+        {
+          return false;
+        }
+      }
+    }
+
+    for (Sequences::const_iterator it = sequences_.begin();
+         it != sequences_.end(); ++it)
+    {
+      if (it->second != NULL)
+      {
+        DcmTagKey tag = ToDcmtkBridge::Convert(it->first);
+
+        DcmSequenceOfItems* sequence = NULL;
+        if (!item.findAndGetSequence(tag, sequence).good() ||
+            sequence == NULL)
+        {
+          return false;
+        }
+
+        bool match = false;
+
+        for (unsigned long i = 0; i < sequence->card(); i++)
+        {
+          if (it->second->MatchInternal(*sequence->getItem(i), encoding))
+          {
+            match = true;
+            break;
+          }
+        }
+
+        if (!match)
+        {
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
+
+
+  DcmDataset* HierarchicalMatcher::ExtractInternal(DcmItem& item,
+                                                   Encoding encoding) const
+  {
+    std::auto_ptr<DcmDataset> dataset(new DcmDataset);
+
+    for (Constraints::const_iterator it = constraints_.begin();
+         it != constraints_.end(); ++it)
+    {
+      DcmTagKey tag = ToDcmtkBridge::Convert(it->first);
+      
+      DcmElement* element = NULL;
+      if (item.findAndGetElement(tag, element).good() &&
+          element != NULL)
+      {
+        std::auto_ptr<DcmElement> cloned(FromDcmtkBridge::CreateElementForTag(it->first));
+        cloned->copyFrom(*element);
+        dataset->insert(cloned.release());
+      }
+    }
+
+    for (Sequences::const_iterator it = sequences_.begin();
+         it != sequences_.end(); ++it)
+    {
+      DcmTagKey tag = ToDcmtkBridge::Convert(it->first);
+
+      DcmSequenceOfItems* sequence = NULL;
+      if (item.findAndGetSequence(tag, sequence).good() &&
+          sequence != NULL)
+      {
+        std::auto_ptr<DcmSequenceOfItems> cloned(new DcmSequenceOfItems(tag));
+
+        for (unsigned long i = 0; i < sequence->card(); i++)
+        {
+          if (it->second == NULL)
+          {
+            cloned->append(new DcmItem(*sequence->getItem(i)));
+          }
+          else if (it->second->MatchInternal(*sequence->getItem(i), encoding))
+          {
+            cloned->append(it->second->ExtractInternal(*sequence->getItem(i), encoding));
+          }
+        }
+
+        dataset->insert(cloned.release());
+      }
+    }
+
+    return dataset.release();
+  }
+
+
+  ParsedDicomFile* HierarchicalMatcher::Extract(ParsedDicomFile& dicom) const
+  {
+    std::auto_ptr<DcmDataset> dataset(ExtractInternal(*dicom.GetDcmtkObject().getDataset(),
+                                                      dicom.GetEncoding()));
+
+    std::auto_ptr<ParsedDicomFile> result(new ParsedDicomFile(*dataset));
+    result->SetEncoding(Encoding_Utf8);
+
+    return result.release();
+  }
 }
--- a/OrthancServer/Search/HierarchicalMatcher.h	Thu Nov 19 17:41:22 2015 +0100
+++ b/OrthancServer/Search/HierarchicalMatcher.h	Thu Nov 19 18:32:00 2015 +0100
@@ -60,6 +60,12 @@
       Setup(query, caseSensitivePN, encoding);
     }
 
+    bool MatchInternal(DcmItem& dicom,
+                       Encoding encoding) const;
+
+    DcmDataset* ExtractInternal(DcmItem& dicom,
+                                Encoding encoding) const;
+
   public:
     HierarchicalMatcher(ParsedDicomFile& query,
                         bool caseSensitivePN);
@@ -67,5 +73,9 @@
     ~HierarchicalMatcher();
 
     std::string Format(const std::string& prefix = "") const;
+
+    bool Match(ParsedDicomFile& dicom) const;
+
+    ParsedDicomFile* Extract(ParsedDicomFile& dicom) const;
   };
 }
--- a/OrthancServer/main.cpp	Thu Nov 19 17:41:22 2015 +0100
+++ b/OrthancServer/main.cpp	Thu Nov 19 18:32:00 2015 +0100
@@ -107,6 +107,7 @@
                       const std::string& remoteIp,
                       const std::string& remoteAet)
   {
+    printf("=====================================================================\n");
     printf("Worklist\n");
 
     bool caseSensitivePN = Configuration::GetGlobalBoolParameter("CaseSensitivePN", false);
@@ -114,6 +115,24 @@
 
     std::cout << matcher.Format();
 
+    for (unsigned int i = 1; i <= 10; i++)
+    {
+      std::string p = "/tmp/worklists/db/OFFIS/item" + boost::lexical_cast<std::string>(i) + ".wl";
+      std::string s;
+      Toolbox::ReadFile(s, p);
+      ParsedDicomFile f(s);
+      std::cout << p << " => " << matcher.Match(f) << std::endl;
+
+      if (matcher.Match(f))
+      {
+        std::auto_ptr<ParsedDicomFile> e(matcher.Extract(f));
+
+        Json::Value v;
+        e->ToJson(v, DicomToJsonFormat_Short, DicomToJsonFlags_Default, 0);
+        std::cout << v;
+      }
+    }
+
     return true;
   }
 };