# HG changeset patch # User Sebastien Jodogne # Date 1597762640 -7200 # Node ID 72047b61570f063675cfd74f7e99424fdbb50f65 # Parent 732ad6c618bada3aa918361bd397eda4f6e868b3# Parent 1fbe54808853ba578016cbeaa8ca04c3997611a9 merge diff -r 732ad6c618ba -r 72047b61570f NEWS --- 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) diff -r 732ad6c618ba -r 72047b61570f OrthancFramework/Sources/DicomFormat/DicomTag.h --- 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); diff -r 732ad6c618ba -r 72047b61570f OrthancServer/Plugins/Samples/ModalityWorklists/Plugin.cpp --- 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 { diff -r 732ad6c618ba -r 72047b61570f OrthancServer/Plugins/Samples/ServeFolders/Plugin.cpp --- 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"; } diff -r 732ad6c618ba -r 72047b61570f OrthancServer/Sources/OrthancConfiguration.h --- 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); diff -r 732ad6c618ba -r 72047b61570f OrthancServer/Sources/OrthancFindRequestHandler.cpp --- 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& sequencesToReturn, const DicomMap* counters, const std::string& defaultPrivateCreator, - const std::map& privateCreators) + const std::map& 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& sequencesToReturn_; std::string defaultPrivateCreator_; // the private creator to use if the group is not defined in the query itself const std::map& 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 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_); } }; diff -r 732ad6c618ba -r 72047b61570f OrthancServer/Sources/OrthancRestApi/OrthancRestSystem.cpp --- 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", ""); diff -r 732ad6c618ba -r 72047b61570f OrthancServer/Sources/ServerContext.cpp --- 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)); diff -r 732ad6c618ba -r 72047b61570f OrthancServer/Sources/main.cpp --- 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 diff -r 732ad6c618ba -r 72047b61570f TODO --- 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: