changeset 1755:39c37a994b2f db-changes

handling of DICOM_TAG_MODALITIES_IN_STUDY
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 28 Oct 2015 12:02:15 +0100
parents 3a4f7dc00f49
children 03b030680e3d
files Core/DicomFormat/DicomMap.cpp Core/DicomFormat/DicomTag.h OrthancServer/OrthancFindRequestHandler.cpp OrthancServer/Search/LookupResource.cpp OrthancServer/Search/LookupResource.h
diffstat 5 files changed, 77 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/Core/DicomFormat/DicomMap.cpp	Wed Oct 28 11:31:58 2015 +0100
+++ b/Core/DicomFormat/DicomMap.cpp	Wed Oct 28 12:02:15 2015 +0100
@@ -69,7 +69,7 @@
     //DicomTag(0x0010, 0x1080), // MilitaryRank
     DicomTag(0x0008, 0x0021),   // SeriesDate
     DicomTag(0x0008, 0x0031),   // SeriesTime
-    DicomTag(0x0008, 0x0060),   // Modality
+    DICOM_TAG_MODALITY,
     DicomTag(0x0008, 0x0070),   // Manufacturer
     DicomTag(0x0008, 0x1010),   // StationName
     DICOM_TAG_SERIES_DESCRIPTION,
--- a/Core/DicomFormat/DicomTag.h	Wed Oct 28 11:31:58 2015 +0100
+++ b/Core/DicomFormat/DicomTag.h	Wed Oct 28 12:02:15 2015 +0100
@@ -109,6 +109,7 @@
 
   static const DicomTag DICOM_TAG_STUDY_DESCRIPTION(0x0008, 0x1030);
   static const DicomTag DICOM_TAG_SERIES_DESCRIPTION(0x0008, 0x103e);
+  static const DicomTag DICOM_TAG_MODALITY(0x0008, 0x0060);
 
   // The following is used for "modify/anonymize" operations
   static const DicomTag DICOM_TAG_SOP_CLASS_UID(0x0008, 0x0016);
--- a/OrthancServer/OrthancFindRequestHandler.cpp	Wed Oct 28 11:31:58 2015 +0100
+++ b/OrthancServer/OrthancFindRequestHandler.cpp	Wed Oct 28 12:02:15 2015 +0100
@@ -307,17 +307,7 @@
       }
 
 #if USE_LOOKUP_RESOURCE == 1
-      if (tag == DICOM_TAG_MODALITIES_IN_STUDY)
-      {
-        // TODO SetModalitiesInStudy(value);
-        // findQuery.SetModalitiesInStudy(value);
-        printf("ICI\n");
-        throw OrthancException(ErrorCode_NotImplemented);
-      }
-      else
-      {
-        finder.Add(tag, value, caseSensitivePN);
-      }
+      finder.AddDicomConstraint(tag, value, caseSensitivePN);
 #else
 
       if (tag == DICOM_TAG_MODALITIES_IN_STUDY)
--- a/OrthancServer/Search/LookupResource.cpp	Wed Oct 28 11:31:58 2015 +0100
+++ b/OrthancServer/Search/LookupResource.cpp	Wed Oct 28 12:02:15 2015 +0100
@@ -309,6 +309,44 @@
     {
       it->second->Apply(candidates, database);
     }
+
+    if (level == ResourceType_Study &&
+        modalitiesInStudy_.get() != NULL)
+    {
+      // There is a constraint on the "ModalitiesInStudy" DICOM
+      // extension. Check out whether one child series has one of the
+      // allowed modalities
+      std::list<int64_t> allStudies, matchingStudies;
+      candidates.Flatten(allStudies);
+ 
+      for (std::list<int64_t>::const_iterator
+             study = allStudies.begin(); study != allStudies.end(); ++study)
+      {
+        std::list<int64_t> childrenSeries;
+        database.GetChildrenInternalId(childrenSeries, *study);
+
+        for (std::list<int64_t>::const_iterator
+               series = childrenSeries.begin(); series != childrenSeries.end(); ++series)
+        {
+          DicomMap tags;
+          database.GetMainDicomTags(tags, *series);
+
+          const DicomValue* value = tags.TestAndGetValue(DICOM_TAG_MODALITY);
+          if (value != NULL &&
+              !value->IsNull() &&
+              !value->IsBinary())
+          {
+            if (modalitiesInStudy_->Match(value->GetContent()))
+            {
+              matchingStudies.push_back(*study);
+              break;
+            }
+          }
+        }
+      }
+
+      candidates.Intersect(matchingStudies);
+    }
   }
 
 
@@ -359,9 +397,24 @@
   }
 
 
-  void LookupResource::Add(const DicomTag& tag,
-                           const std::string& dicomQuery,
-                           bool caseSensitivePN)
+  void LookupResource::SetModalitiesInStudy(const std::string& modalities)
+  {
+    modalitiesInStudy_.reset(new ListConstraint(DICOM_TAG_MODALITIES_IN_STUDY, 
+                                                true /* case sensitive */));
+    
+    std::vector<std::string> items;
+    Toolbox::TokenizeString(items, modalities, '\\');
+    
+    for (size_t i = 0; i < items.size(); i++)
+    {
+      modalitiesInStudy_->AddAllowedValue(items[i]);
+    }
+  }
+
+
+  void LookupResource::AddDicomConstraint(const DicomTag& tag,
+                                          const std::string& dicomQuery,
+                                          bool caseSensitivePN)
   {
     ValueRepresentation vr = FromDcmtkBridge::GetValueRepresentation(tag);
 
@@ -374,10 +427,14 @@
     // http://www.itk.org/Wiki/DICOM_QueryRetrieve_Explained
     // http://dicomiseasy.blogspot.be/2012/01/dicom-queryretrieve-part-i.html  
 
-    if ((vr == ValueRepresentation_Date ||
-         vr == ValueRepresentation_DateTime ||
-         vr == ValueRepresentation_Time) &&
-        dicomQuery.find('-') != std::string::npos)
+    if (tag == DICOM_TAG_MODALITIES_IN_STUDY)
+    {
+      SetModalitiesInStudy(dicomQuery);
+    }
+    else if ((vr == ValueRepresentation_Date ||
+              vr == ValueRepresentation_DateTime ||
+              vr == ValueRepresentation_Time) &&
+             dicomQuery.find('-') != std::string::npos)
     {
       /**
        * Range matching is only defined for TM, DA and DT value
--- a/OrthancServer/Search/LookupResource.h	Wed Oct 28 11:31:58 2015 +0100
+++ b/OrthancServer/Search/LookupResource.h	Wed Oct 28 12:02:15 2015 +0100
@@ -32,7 +32,7 @@
 
 #pragma once
 
-#include "IFindConstraint.h"
+#include "ListConstraint.h"
 #include "SetOfResources.h"
 
 #include <memory>
@@ -66,9 +66,10 @@
 
     typedef std::map<ResourceType, Level*>  Levels;
 
-    ResourceType level_;
-    Levels       levels_;
-    Constraints  unoptimizedConstraints_;
+    ResourceType                    level_;
+    Levels                          levels_;
+    Constraints                     unoptimizedConstraints_; 
+    std::auto_ptr<ListConstraint>   modalitiesInStudy_;
 
     bool AddInternal(ResourceType level,
                      std::auto_ptr<IFindConstraint>& constraint);
@@ -87,11 +88,13 @@
       return level_;
     }
 
+    void SetModalitiesInStudy(const std::string& modalities); 
+
     void Add(IFindConstraint* constraint);   // Takes ownership
 
-    void Add(const DicomTag& tag,
-             const std::string& dicomQuery,
-             bool caseSensitivePN);
+    void AddDicomConstraint(const DicomTag& tag,
+                            const std::string& dicomQuery,
+                            bool caseSensitivePN);
 
     void FindCandidates(std::list<int64_t>& result,
                         IDatabaseWrapper& database) const;