changeset 4149:72047b61570f

merge
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 18 Aug 2020 16:57:20 +0200
parents 732ad6c618ba (current diff) 1fbe54808853 (diff)
children b56f3a37a4a1
files
diffstat 10 files changed, 43 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Tue Aug 18 16:56:33 2020 +0200
+++ b/NEWS	Tue Aug 18 16:57:20 2020 +0200
@@ -1,8 +1,10 @@
 Pending changes in the mainline
 ===============================
 
+* Add missing tag "Retrieve AE Title (0008,0054)" in C-FIND SCP responses
 * Fix DICOM SCP filters if some query tag has more than 256 characters
 * "/series/.../ordered-slices" supports spaces in Image Position/Orientation Patient tags
+* New config option "Worklist.LimitAnswers" for the sample modality worklist plugin
 
 
 Version 1.7.2 (2020-07-08)
--- a/OrthancFramework/Sources/DicomFormat/DicomTag.h	Tue Aug 18 16:56:33 2020 +0200
+++ b/OrthancFramework/Sources/DicomFormat/DicomTag.h	Tue Aug 18 16:57:20 2020 +0200
@@ -125,6 +125,7 @@
   static const DicomTag DICOM_TAG_SPECIFIC_CHARACTER_SET(0x0008, 0x0005);
   static const DicomTag DICOM_TAG_QUERY_RETRIEVE_LEVEL(0x0008, 0x0052);
   static const DicomTag DICOM_TAG_MODALITIES_IN_STUDY(0x0008, 0x0061);
+  static const DicomTag DICOM_TAG_RETRIEVE_AE_TITLE(0x0008, 0x0054);
 
   // Tags for images
   static const DicomTag DICOM_TAG_COLUMNS(0x0028, 0x0011);
--- a/OrthancServer/Plugins/Samples/ModalityWorklists/Plugin.cpp	Tue Aug 18 16:56:33 2020 +0200
+++ b/OrthancServer/Plugins/Samples/ModalityWorklists/Plugin.cpp	Tue Aug 18 16:57:20 2020 +0200
@@ -31,6 +31,7 @@
 
 static std::string folder_;
 static bool filterIssuerAet_ = false;
+static unsigned int limitAnswers_ = 0;
 
 /**
  * This is the main function for matching a DICOM worklist against a query.
@@ -150,8 +151,8 @@
 
     fs::path source(folder_);
     fs::directory_iterator end;
-    int parsedFilesCount = 0;
-    int matchedWorklistCount = 0;
+    unsigned int parsedFilesCount = 0;
+    unsigned int matchedWorklistCount = 0;
 
     try
     {
@@ -171,6 +172,16 @@
             // We found a worklist (i.e. a DICOM find with extension ".wl"), match it against the query
             if (MatchWorklist(answers, query, *matcher, it->path().string()))
             {
+              if (limitAnswers_ != 0 &&
+                  matchedWorklistCount >= limitAnswers_)
+              {
+                // Too many answers are to be returned wrt. the
+                // "LimitAnswers" configuration parameter. Mark the
+                // C-FIND result as incomplete.
+                OrthancPluginWorklistMarkIncomplete(OrthancPlugins::GetGlobalContext(), answers);
+                return OrthancPluginErrorCode_Success;
+              }
+              
               OrthancPlugins::LogInfo("Worklist matched: " + it->path().string());
               matchedWorklistCount++;
             }
@@ -179,9 +190,9 @@
       }
 
       std::ostringstream message;
-      message << "Worklist C-Find: parsed " << parsedFilesCount << " files, found " << matchedWorklistCount << " match(es)";
+      message << "Worklist C-Find: parsed " << parsedFilesCount
+              << " files, found " << matchedWorklistCount << " match(es)";
       OrthancPlugins::LogInfo(message.str());
-
     }
     catch (fs::filesystem_error&)
     {
@@ -189,9 +200,6 @@
       return OrthancPluginErrorCode_DirectoryExpected;
     }
 
-    // Uncomment the following line if too many answers are to be returned
-    // OrthancPluginMarkWorklistAnswersIncomplete(OrthancPlugins::GetGlobalContext(), answers);
-
     return OrthancPluginErrorCode_Success;
   }
   catch (OrthancPlugins::PluginException& e)
@@ -239,6 +247,7 @@
       }
 
       filterIssuerAet_ = worklists.GetBooleanValue("FilterIssuerAet", false);
+      limitAnswers_ = worklists.GetUnsignedIntegerValue("LimitAnswers", 0);
     }
     else
     {
--- a/OrthancServer/Plugins/Samples/ServeFolders/Plugin.cpp	Tue Aug 18 16:56:33 2020 +0200
+++ b/OrthancServer/Plugins/Samples/ServeFolders/Plugin.cpp	Tue Aug 18 16:57:20 2020 +0200
@@ -70,6 +70,8 @@
   extensions_["wasm"] = "application/wasm";
   extensions_["woff"] = "application/x-font-woff";
   extensions_["xml"]  = "application/xml";
+  extensions_["pdf"]  = "application/pdf";
+  extensions_["woff2"] = "font/woff2";
 }
 
 
--- a/OrthancServer/Sources/OrthancConfiguration.h	Tue Aug 18 16:56:33 2020 +0200
+++ b/OrthancServer/Sources/OrthancConfiguration.h	Tue Aug 18 16:57:20 2020 +0200
@@ -237,6 +237,11 @@
 
     std::string GetDefaultPrivateCreator() const;
 
+    std::string GetOrthancAET() const
+    {
+      return GetStringParameter("DicomAet", "ORTHANC");
+    }
+
     static void DefaultExtractDicomSummary(DicomMap& target,
                                            ParsedDicomFile& dicom);
     
--- a/OrthancServer/Sources/OrthancFindRequestHandler.cpp	Tue Aug 18 16:56:33 2020 +0200
+++ b/OrthancServer/Sources/OrthancFindRequestHandler.cpp	Tue Aug 18 16:57:20 2020 +0200
@@ -304,7 +304,8 @@
                         const std::list<DicomTag>& sequencesToReturn,
                         const DicomMap* counters,
                         const std::string& defaultPrivateCreator,
-                        const std::map<uint16_t, std::string>& privateCreators)
+                        const std::map<uint16_t, std::string>& privateCreators,
+                        const std::string& retrieveAet)
   {
     DicomMap match;
 
@@ -319,6 +320,13 @@
     
     DicomMap result;
 
+    /**
+     * Add the mandatory "Retrieve AE Title (0008,0054)" tag, which was missing in Orthanc <= 1.7.2.
+     * http://dicom.nema.org/medical/dicom/current/output/html/part04.html#sect_C.4.1.1.3.2
+     * https://groups.google.com/g/orthanc-users/c/-7zNTKR_PMU/m/kfjwzEVNAgAJ
+     **/
+    result.SetValue(DICOM_TAG_RETRIEVE_AE_TITLE, retrieveAet, false /* not binary */);
+
     for (size_t i = 0; i < query.GetSize(); i++)
     {
       if (query.GetElement(i).GetTag() == DICOM_TAG_QUERY_RETRIEVE_LEVEL)
@@ -504,6 +512,7 @@
     const std::list<DicomTag>&  sequencesToReturn_;
     std::string                 defaultPrivateCreator_;       // the private creator to use if the group is not defined in the query itself
     const std::map<uint16_t, std::string>& privateCreators_;  // the private creators defined in the query itself
+    std::string                 retrieveAet_;
 
   public:
     LookupVisitor(DicomFindAnswers&  answers,
@@ -525,6 +534,7 @@
       {
         OrthancConfiguration::ReaderLock lock;
         defaultPrivateCreator_ = lock.GetConfiguration().GetDefaultPrivateCreator();
+        retrieveAet_ = lock.GetConfiguration().GetOrthancAET();
       }
     }
 
@@ -566,8 +576,8 @@
     {
       std::unique_ptr<DicomMap> counters(ComputeCounters(context_, instanceId, level_, query_));
 
-      AddAnswer(answers_, mainDicomTags, dicomAsJson,
-                queryAsArray_, sequencesToReturn_, counters.get(), defaultPrivateCreator_, privateCreators_);
+      AddAnswer(answers_, mainDicomTags, dicomAsJson, queryAsArray_, sequencesToReturn_,
+                counters.get(), defaultPrivateCreator_, privateCreators_, retrieveAet_);
     }
   };
 
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestSystem.cpp	Tue Aug 18 16:56:33 2020 +0200
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestSystem.cpp	Tue Aug 18 16:57:20 2020 +0200
@@ -69,7 +69,7 @@
 
     {
       OrthancConfiguration::ReaderLock lock;
-      result["DicomAet"] = lock.GetConfiguration().GetStringParameter("DicomAet", "ORTHANC");
+      result["DicomAet"] = lock.GetConfiguration().GetOrthancAET();
       result["DicomPort"] = lock.GetConfiguration().GetUnsignedIntegerParameter("DicomPort", 4242);
       result["HttpPort"] = lock.GetConfiguration().GetUnsignedIntegerParameter("HttpPort", 8042);
       result["Name"] = lock.GetConfiguration().GetStringParameter("Name", "");
--- a/OrthancServer/Sources/ServerContext.cpp	Tue Aug 18 16:56:33 2020 +0200
+++ b/OrthancServer/Sources/ServerContext.cpp	Tue Aug 18 16:57:20 2020 +0200
@@ -280,7 +280,7 @@
           new SharedArchive(lock.GetConfiguration().GetUnsignedIntegerParameter("QueryRetrieveSize", 100)));
         mediaArchive_.reset(
           new SharedArchive(lock.GetConfiguration().GetUnsignedIntegerParameter("MediaArchiveSize", 1)));
-        defaultLocalAet_ = lock.GetConfiguration().GetStringParameter("DicomAet", "ORTHANC");
+        defaultLocalAet_ = lock.GetConfiguration().GetOrthancAET();
         jobsEngine_.SetWorkersCount(lock.GetConfiguration().GetUnsignedIntegerParameter("ConcurrentJobs", 2));
         saveJobs_ = lock.GetConfiguration().GetBooleanParameter("SaveJobs", true);
         metricsRegistry_->SetEnabled(lock.GetConfiguration().GetBooleanParameter("MetricsEnabled", true));
--- a/OrthancServer/Sources/main.cpp	Tue Aug 18 16:56:33 2020 +0200
+++ b/OrthancServer/Sources/main.cpp	Tue Aug 18 16:57:20 2020 +0200
@@ -1073,7 +1073,7 @@
       dicomServer.SetCalledApplicationEntityTitleCheck(lock.GetConfiguration().GetBooleanParameter("DicomCheckCalledAet", false));
       dicomServer.SetAssociationTimeout(lock.GetConfiguration().GetUnsignedIntegerParameter("DicomScpTimeout", 30));
       dicomServer.SetPortNumber(lock.GetConfiguration().GetUnsignedIntegerParameter("DicomPort", 4242));
-      dicomServer.SetApplicationEntityTitle(lock.GetConfiguration().GetStringParameter("DicomAet", "ORTHANC"));
+      dicomServer.SetApplicationEntityTitle(lock.GetConfiguration().GetOrthancAET());
     }
 
 #if ORTHANC_ENABLE_PLUGINS == 1
--- a/TODO	Tue Aug 18 16:56:33 2020 +0200
+++ b/TODO	Tue Aug 18 16:57:20 2020 +0200
@@ -57,9 +57,7 @@
 --------
 
 * Support "Retrieve AE Title" (0008,0054) in C-FIND:
-  - On SCP side:
-    http://dicom.nema.org/medical/DICOM/2019a/output/chtml/part04/sect_C.4.html#sect_C.4.1.1.3.2
-    => As Orthanc is non-distributed, it should simply reply using the AET provided by the caller
+  - On SCP side: done by https://hg.orthanc-server.com/orthanc/rev/1ec3e1e18f50
   - On SCU side:
     https://groups.google.com/d/msg/orthanc-users/wPl0g5mqZco/5X1Z8tEzBgAJ
 * Support "Instance Availability" (0008,0056) in C-FIND: