changeset 1366:a3559b66fba7 query-retrieve

move primitives
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 22 May 2015 16:17:28 +0200
parents 38ce915cb455
children fe6e5a9f1ea2
files OrthancServer/DicomProtocol/DicomUserConnection.cpp OrthancServer/DicomProtocol/DicomUserConnection.h OrthancServer/OrthancInitialization.cpp OrthancServer/main.cpp
diffstat 4 files changed, 192 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/DicomProtocol/DicomUserConnection.cpp	Thu May 21 17:03:15 2015 +0200
+++ b/OrthancServer/DicomProtocol/DicomUserConnection.cpp	Fri May 22 16:17:28 2015 +0200
@@ -337,6 +337,16 @@
   }
 
 
+  namespace
+  {
+    struct FindPayload
+    {
+      DicomFindAnswers* answers;
+      std::string       level;
+    };
+  }
+
+
   static void FindCallback(
     /* in */
     void *callbackData,
@@ -346,13 +356,19 @@
     DcmDataset *responseIdentifiers /* pending response identifiers */
     )
   {
-    DicomFindAnswers& answers = *reinterpret_cast<DicomFindAnswers*>(callbackData);
+    FindPayload& payload = *reinterpret_cast<FindPayload*>(callbackData);
 
     if (responseIdentifiers != NULL)
     {
       DicomMap m;
       FromDcmtkBridge::Convert(m, *responseIdentifiers);
-      answers.Add(m);
+
+      if (!m.HasTag(DICOM_TAG_QUERY_RETRIEVE_LEVEL))
+      {
+        m.SetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL, payload.level);
+      }
+
+      payload.answers->Add(m);
     }
   }
 
@@ -362,11 +378,15 @@
   {
     CheckIsOpen();
 
+    FindPayload payload;
+    payload.answers = &result;
+
     const char* sopClass;
     std::auto_ptr<DcmDataset> dataset(ToDcmtkBridge::Convert(fields));
     switch (model)
     {
       case FindRootModel_Patient:
+        payload.level = "PATIENT";
         DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "PATIENT");
         sopClass = UID_FINDPatientRootQueryRetrieveInformationModel;
       
@@ -381,6 +401,7 @@
         break;
 
       case FindRootModel_Study:
+        payload.level = "STUDY";
         DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "STUDY");
         sopClass = UID_FINDStudyRootQueryRetrieveInformationModel;
 
@@ -395,6 +416,7 @@
         break;
 
       case FindRootModel_Series:
+        payload.level = "SERIES";
         DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "SERIES");
         sopClass = UID_FINDStudyRootQueryRetrieveInformationModel;
 
@@ -413,6 +435,7 @@
         break;
 
       case FindRootModel_Instance:
+        payload.level = "INSTANCE";
         if (manufacturer_ == ModalityManufacturer_ClearCanvas ||
             manufacturer_ == ModalityManufacturer_Dcm4Chee)
         {
@@ -467,7 +490,7 @@
     T_DIMSE_C_FindRSP response;
     DcmDataset* statusDetail = NULL;
     OFCondition cond = DIMSE_findUser(pimpl_->assoc_, presID, &request, dataset.get(),
-                                      FindCallback, &result,
+                                      FindCallback, &payload,
                                       /*opt_blockMode*/ DIMSE_BLOCKING, 
                                       /*opt_dimse_timeout*/ pimpl_->dimseTimeout_,
                                       &response, &statusDetail);
@@ -534,8 +557,8 @@
   }
 
 
-  void DicomUserConnection::Move(const std::string& targetAet,
-                                 const DicomMap& fields)
+  void DicomUserConnection::MoveInternal(const std::string& targetAet,
+                                         const DicomMap& fields)
   {
     CheckIsOpen();
 
@@ -830,33 +853,86 @@
   }
 
 
-  void DicomUserConnection::MoveSeries(const std::string& targetAet,
-                                       const DicomMap& findResult)
+  static void TestAndCopyTag(DicomMap& result,
+                             const DicomMap& source,
+                             const DicomTag& tag)
+  {
+    if (!source.HasTag(tag))
+    {
+      throw OrthancException(ErrorCode_BadRequest);
+    }
+    else
+    {
+      result.SetValue(tag, source.GetValue(tag));
+    }
+  }
+
+
+  void DicomUserConnection::Move(const std::string& targetAet,
+                                 const DicomMap& findResult)
   {
-    DicomMap simplified;
-    simplified.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, findResult.GetValue(DICOM_TAG_STUDY_INSTANCE_UID));
-    simplified.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, findResult.GetValue(DICOM_TAG_SERIES_INSTANCE_UID));
-    Move(targetAet, simplified);
+    if (!findResult.HasTag(DICOM_TAG_QUERY_RETRIEVE_LEVEL))
+    {
+      throw OrthancException(ErrorCode_InternalError);
+    }
+
+    const std::string tmp = findResult.GetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL).AsString();
+    ResourceType level = StringToResourceType(tmp.c_str());
+
+    DicomMap move;
+    switch (level)
+    {
+      case ResourceType_Patient:
+        TestAndCopyTag(move, findResult, DICOM_TAG_PATIENT_ID);
+        break;
+
+      case ResourceType_Study:
+        TestAndCopyTag(move, findResult, DICOM_TAG_STUDY_INSTANCE_UID);
+        break;
+
+      case ResourceType_Series:
+        TestAndCopyTag(move, findResult, DICOM_TAG_STUDY_INSTANCE_UID);
+        TestAndCopyTag(move, findResult, DICOM_TAG_SERIES_INSTANCE_UID);
+        break;
+
+      case ResourceType_Instance:
+        TestAndCopyTag(move, findResult, DICOM_TAG_STUDY_INSTANCE_UID);
+        TestAndCopyTag(move, findResult, DICOM_TAG_SERIES_INSTANCE_UID);
+        TestAndCopyTag(move, findResult, DICOM_TAG_SOP_INSTANCE_UID);
+        break;
+
+      default:
+        throw OrthancException(ErrorCode_InternalError);
+    }
+
+    MoveInternal(targetAet, move);
+  }
+
+
+  void DicomUserConnection::MovePatient(const std::string& targetAet,
+                                        const std::string& patientId)
+  {
+    DicomMap query;
+    query.SetValue(DICOM_TAG_PATIENT_ID, patientId);
+    MoveInternal(targetAet, query);
+  }
+
+  void DicomUserConnection::MoveStudy(const std::string& targetAet,
+                                      const std::string& studyUid)
+  {
+    DicomMap query;
+    query.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, studyUid);
+    MoveInternal(targetAet, query);
   }
 
   void DicomUserConnection::MoveSeries(const std::string& targetAet,
                                        const std::string& studyUid,
                                        const std::string& seriesUid)
   {
-    DicomMap map;
-    map.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, studyUid);
-    map.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, seriesUid);
-    Move(targetAet, map);
-  }
-
-  void DicomUserConnection::MoveInstance(const std::string& targetAet,
-                                         const DicomMap& findResult)
-  {
-    DicomMap simplified;
-    simplified.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, findResult.GetValue(DICOM_TAG_STUDY_INSTANCE_UID));
-    simplified.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, findResult.GetValue(DICOM_TAG_SERIES_INSTANCE_UID));
-    simplified.SetValue(DICOM_TAG_SOP_INSTANCE_UID, findResult.GetValue(DICOM_TAG_SOP_INSTANCE_UID));
-    Move(targetAet, simplified);
+    DicomMap query;
+    query.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, studyUid);
+    query.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, seriesUid);
+    MoveInternal(targetAet, query);
   }
 
   void DicomUserConnection::MoveInstance(const std::string& targetAet,
@@ -864,11 +940,11 @@
                                          const std::string& seriesUid,
                                          const std::string& instanceUid)
   {
-    DicomMap map;
-    map.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, studyUid);
-    map.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, seriesUid);
-    map.SetValue(DICOM_TAG_SOP_INSTANCE_UID, instanceUid);
-    Move(targetAet, map);
+    DicomMap query;
+    query.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, studyUid);
+    query.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, seriesUid);
+    query.SetValue(DICOM_TAG_SOP_INSTANCE_UID, instanceUid);
+    MoveInternal(targetAet, query);
   }
 
 
--- a/OrthancServer/DicomProtocol/DicomUserConnection.h	Thu May 21 17:03:15 2015 +0200
+++ b/OrthancServer/DicomProtocol/DicomUserConnection.h	Fri May 22 16:17:28 2015 +0200
@@ -76,8 +76,8 @@
               FindRootModel model,
               const DicomMap& fields);
 
-    void Move(const std::string& targetAet,
-              const DicomMap& fields);
+    void MoveInternal(const std::string& targetAet,
+                      const DicomMap& fields);
 
     void ResetStorageSOPClasses();
 
@@ -162,17 +162,20 @@
     void FindInstance(DicomFindAnswers& result,
                       const DicomMap& fields);
 
-    void MoveSeries(const std::string& targetAet,
-                    const DicomMap& findResult);
+    void Move(const std::string& targetAet,
+              const DicomMap& findResult);
+
+    void MovePatient(const std::string& targetAet,
+                     const std::string& patientId);
+
+    void MoveStudy(const std::string& targetAet,
+                   const std::string& studyUid);
 
     void MoveSeries(const std::string& targetAet,
                     const std::string& studyUid,
                     const std::string& seriesUid);
 
     void MoveInstance(const std::string& targetAet,
-                      const DicomMap& findResult);
-
-    void MoveInstance(const std::string& targetAet,
                       const std::string& studyUid,
                       const std::string& seriesUid,
                       const std::string& instanceUid);
--- a/OrthancServer/OrthancInitialization.cpp	Thu May 21 17:03:15 2015 +0200
+++ b/OrthancServer/OrthancInitialization.cpp	Fri May 22 16:17:28 2015 +0200
@@ -238,7 +238,8 @@
   {
     boost::mutex::scoped_lock lock(globalMutex_);
 
-    if (configuration_->isMember(parameter))
+    if (configuration_.get() != NULL &&
+        configuration_->isMember(parameter))
     {
       return (*configuration_) [parameter].asString();
     }
@@ -254,7 +255,8 @@
   {
     boost::mutex::scoped_lock lock(globalMutex_);
 
-    if (configuration_->isMember(parameter))
+    if (configuration_.get() != NULL &&
+        configuration_->isMember(parameter))
     {
       return (*configuration_) [parameter].asInt();
     }
@@ -270,7 +272,8 @@
   {
     boost::mutex::scoped_lock lock(globalMutex_);
 
-    if (configuration_->isMember(parameter))
+    if (configuration_.get() != NULL &&
+        configuration_->isMember(parameter))
     {
       return (*configuration_) [parameter].asBool();
     }
@@ -286,6 +289,11 @@
   {
     boost::mutex::scoped_lock lock(globalMutex_);
 
+    if (configuration_.get() == NULL)
+    {
+      throw OrthancException(ErrorCode_InexistentItem);
+    }
+       
     if (!configuration_->isMember("DicomModalities"))
     {
       throw OrthancException(ErrorCode_BadFileFormat);
@@ -318,6 +326,11 @@
   {
     boost::mutex::scoped_lock lock(globalMutex_);
 
+    if (configuration_.get() == NULL)
+    {
+      throw OrthancException(ErrorCode_InexistentItem);
+    }
+       
     if (!configuration_->isMember("OrthancPeers"))
     {
       throw OrthancException(ErrorCode_BadFileFormat);
@@ -352,7 +365,8 @@
 
     target.clear();
   
-    if (!configuration_->isMember(parameter))
+    if (configuration_.get() == NULL ||
+        !configuration_->isMember(parameter))
     {
       return true;
     }
@@ -409,7 +423,8 @@
 
     httpServer.ClearUsers();
 
-    if (!configuration_->isMember("RegisteredUsers"))
+    if (configuration_.get() == NULL ||
+        !configuration_->isMember("RegisteredUsers"))
     {
       return;
     }
@@ -470,7 +485,8 @@
 
     target.clear();
   
-    if (!configuration_->isMember(key))
+    if (configuration_.get() == NULL ||
+        !configuration_->isMember(key))
     {
       return;
     }
@@ -571,6 +587,11 @@
   {
     boost::mutex::scoped_lock lock(globalMutex_);
 
+    if (configuration_.get() == NULL)
+    {
+      throw OrthancException(ErrorCode_InternalError);
+    }
+
     if (!configuration_->isMember("DicomModalities"))
     {
       (*configuration_) ["DicomModalities"] = Json::objectValue;
@@ -594,6 +615,11 @@
   {
     boost::mutex::scoped_lock lock(globalMutex_);
 
+    if (configuration_.get() == NULL)
+    {
+      throw OrthancException(ErrorCode_InternalError);
+    }
+
     if (!configuration_->isMember("DicomModalities"))
     {
       throw OrthancException(ErrorCode_BadFileFormat);
@@ -614,6 +640,11 @@
   {
     boost::mutex::scoped_lock lock(globalMutex_);
 
+    if (configuration_.get() == NULL)
+    {
+      throw OrthancException(ErrorCode_InternalError);
+    }
+
     if (!configuration_->isMember("OrthancPeers"))
     {
       (*configuration_) ["OrthancPeers"] = Json::objectValue;
@@ -637,6 +668,11 @@
   {
     boost::mutex::scoped_lock lock(globalMutex_);
 
+    if (configuration_.get() == NULL)
+    {
+      throw OrthancException(ErrorCode_InternalError);
+    }
+
     if (!configuration_->isMember("OrthancPeers"))
     {
       throw OrthancException(ErrorCode_BadFileFormat);
--- a/OrthancServer/main.cpp	Thu May 21 17:03:15 2015 +0200
+++ b/OrthancServer/main.cpp	Fri May 22 16:17:28 2015 +0200
@@ -51,6 +51,7 @@
 #include "ServerToolbox.h"
 #include "../Plugins/Engine/PluginsManager.h"
 #include "../Plugins/Engine/OrthancPlugins.h"
+#include "FromDcmtkBridge.h"
 
 using namespace Orthanc;
 
@@ -531,6 +532,39 @@
     }
 
     LOG(WARNING) << "Orthanc has started";
+
+
+    if (1)
+    {
+      DicomUserConnection c;
+      c.SetLocalApplicationEntityTitle("ORTHANC");
+      c.SetRemoteApplicationEntityTitle("ORTHANC");
+      c.SetRemoteHost("localhost");
+      c.SetRemotePort(4343);
+      c.Open();
+
+      DicomMap m; // Cardiac
+      m.SetValue(DICOM_TAG_PATIENT_ID, "3390592L");
+      //m.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "1.3.51.0.1.1.192.168.29.133.1681753.1681732");
+      //m.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "1.3.12.2.1107.5.2.33.37097.2012041612474981424569674.0.0.0");
+      //m.SetValue(DICOM_TAG_SOP_INSTANCE_UID, "1.3.12.2.1107.5.2.33.37097.2012041612485535037669708");
+
+      DicomFindAnswers fnd;
+      c.FindPatient(fnd, m);
+      //c.FindInstance(fnd, m);
+      //c.FindSeries(fnd, m);
+      //c.FindStudy(fnd, m);
+
+      for (size_t i = 0; i < fnd.GetSize(); i++)
+      {
+        FromDcmtkBridge::Print(stdout, fnd.GetAnswer(i));
+        c.Move("ORTHANC", fnd.GetAnswer(i));
+      }
+
+      printf("ok %d\n", fnd.GetSize());
+    }
+
+
     Toolbox::ServerBarrier(restApi.ResetRequestReceivedFlag());
     isReset = restApi.ResetRequestReceivedFlag();
 
@@ -638,29 +672,6 @@
   int status = 0;
   try
   {
-    if (1)
-    {
-      DicomUserConnection c;
-      c.SetLocalApplicationEntityTitle("ORTHANC");
-      c.SetRemoteApplicationEntityTitle("ORTHANC");
-      c.SetRemoteHost("localhost");
-      c.SetRemotePort(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());
-    }
-
-
     for (;;)
     {
       OrthancInitialize(configurationFile);