changeset 123:ed0003f6102c wasm

dynamic loading of rt-struct renderers
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sat, 07 Oct 2017 13:11:12 +0200
parents e3433dabfb8d
children 5099aaa53bd0
files Applications/Samples/SingleVolumeApplication.h Framework/Layers/DicomStructureSetRendererFactory.cpp Framework/Layers/DicomStructureSetRendererFactory.h Platforms/Generic/WebServiceGetCommand.cpp Platforms/Generic/WebServicePostCommand.cpp
diffstat 5 files changed, 155 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Samples/SingleVolumeApplication.h	Fri Oct 06 17:25:08 2017 +0200
+++ b/Applications/Samples/SingleVolumeApplication.h	Sat Oct 07 13:11:12 2017 +0200
@@ -88,9 +88,6 @@
       };
 
 
-      std::auto_ptr<DicomStructureSet>  struct_;
-      
-
     public:
       virtual void DeclareCommandLineOptions(boost::program_options::options_description& options)
       {
@@ -202,14 +199,6 @@
           widget->SetLayerStyle(0, s);
         }
 #else
-        {
-          const std::string s = "54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9";  // IBA
-          //const std::string s = "17cd032b-ad92a438-ca05f06a-f9e96668-7e3e9e20";  // 0522c0001 TCIA
-          
-          OrthancPlugins::OrthancHttpConnection orthanc;
-          struct_.reset(DicomStructureSet::SynchronousLoad(orthanc, s));
-        }
-        
         std::auto_ptr<OrthancVolumeImage> ct(new OrthancVolumeImage(context.GetWebService(), false));
         //ct->ScheduleLoadSeries("dd069910-4f090474-7d2bba07-e5c10783-f9e4fb1d");
         ct->ScheduleLoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa");  // IBA
@@ -222,9 +211,12 @@
         //pet->ScheduleLoadInstance("830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb");  // IBA 3
         //pet->ScheduleLoadInstance("269f26f4-0c83eeeb-2e67abbd-5467a40f-f1bec90c");  // 0522c0001 TCIA
 
+        const std::string s = "54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9";  // IBA
+        //const std::string s = "17cd032b-ad92a438-ca05f06a-f9e96668-7e3e9e20";  // 0522c0001 TCIA
+        
         widget->AddLayer(new VolumeImageSource(*ct));
         widget->AddLayer(new VolumeImageSource(*pet));
-        widget->AddLayer(new DicomStructureSetRendererFactory(*struct_));
+        widget->AddLayer(new DicomStructureSetRendererFactory(context.GetWebService(), s));
         
         context.AddInteractor(new Interactor(*pet, *widget, projection, 1));
         //context.AddInteractor(new VolumeImageInteractor(*ct, *widget, projection));
--- a/Framework/Layers/DicomStructureSetRendererFactory.cpp	Fri Oct 06 17:25:08 2017 +0200
+++ b/Framework/Layers/DicomStructureSetRendererFactory.cpp	Sat Oct 07 13:11:12 2017 +0200
@@ -21,6 +21,8 @@
 
 #include "DicomStructureSetRendererFactory.h"
 
+#include "../Toolbox/MessagingToolbox.h"
+
 #include <Core/OrthancException.h>
 
 namespace OrthancStone
@@ -70,12 +72,140 @@
   };
 
 
+  class DicomStructureSetRendererFactory::Operation : public Orthanc::IDynamicObject
+  {
+  public:
+    enum Type
+    {
+      Type_LoadStructureSet,
+      Type_LookupSopInstanceUid,
+      Type_LoadReferencedSlice
+    };
+    
+  private:
+    Type         type_;
+    std::string  value_;
+
+  public:
+    Operation(Type type,
+              const std::string& value) :
+      type_(type),
+      value_(value)
+    {
+    }
+
+    Type GetType() const
+    {
+      return type_;
+    }
+
+    const std::string& GetIdentifier() const
+    {
+      return value_;
+    }
+  };
+
+
+  void DicomStructureSetRendererFactory::NotifyError(const std::string& uri,
+                                                     Orthanc::IDynamicObject* payload)
+  {
+    // TODO
+  }
+
+  
+  void DicomStructureSetRendererFactory::NotifySuccess(const std::string& uri,
+                                                       const void* answer,
+                                                       size_t answerSize,
+                                                       Orthanc::IDynamicObject* payload)
+  {
+    std::auto_ptr<Operation> op(dynamic_cast<Operation*>(payload));
+
+    switch (op->GetType())
+    {
+      case Operation::Type_LoadStructureSet:
+      {
+        OrthancPlugins::FullOrthancDataset dataset(answer, answerSize);
+        structureSet_.reset(new DicomStructureSet(dataset));
+
+        std::set<std::string> instances;
+        structureSet_->GetReferencedInstances(instances);
+
+        for (std::set<std::string>::const_iterator it = instances.begin();
+             it != instances.end(); ++it)
+        {
+          orthanc_.SchedulePostRequest(*this, "/tools/lookup", *it,
+                                       new Operation(Operation::Type_LookupSopInstanceUid, *it));
+        }
+        
+        break;
+      }
+        
+      case Operation::Type_LookupSopInstanceUid:
+      {
+        Json::Value lookup;
+        
+        if (MessagingToolbox::ParseJson(lookup, answer, answerSize))
+        {
+          if (lookup.type() != Json::arrayValue ||
+              lookup.size() != 1 ||
+              !lookup[0].isMember("Type") ||
+              !lookup[0].isMember("Path") ||
+              lookup[0]["Type"].type() != Json::stringValue ||
+              lookup[0]["ID"].type() != Json::stringValue ||
+              lookup[0]["Type"].asString() != "Instance")
+          {
+            throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);          
+          }
+
+          const std::string& instance = lookup[0]["ID"].asString();
+          orthanc_.ScheduleGetRequest(*this, "/instances/" + instance + "/tags",
+                                      new Operation(Operation::Type_LoadReferencedSlice, instance));
+        }
+        else
+        {
+          // TODO
+        }
+        
+        break;
+      }
+
+      case Operation::Type_LoadReferencedSlice:
+      {
+        OrthancPlugins::FullOrthancDataset dataset(answer, answerSize);
+
+        Orthanc::DicomMap slice;
+        MessagingToolbox::ConvertDataset(slice, dataset);
+        structureSet_->AddReferencedSlice(slice);
+
+        LayerSourceBase::NotifyContentChange();
+
+        break;
+      }
+      
+      default:
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+    }
+  } 
+
+  
+  DicomStructureSetRendererFactory::DicomStructureSetRendererFactory(IWebService& orthanc,
+                                                                     const std::string& instance) :
+    orthanc_(orthanc)
+  {
+    const std::string uri = "/instances/" + instance + "/tags?ignore-length=3006-0050";
+    orthanc_.ScheduleGetRequest(*this, uri, new Operation(Operation::Type_LoadStructureSet, instance));
+  }
+  
+  
   void DicomStructureSetRendererFactory::ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice)
   {
     bool isOpposite;
-    if (GeometryToolbox::IsParallelOrOpposite(isOpposite, viewportSlice.GetNormal(), structureSet_.GetNormal()))
+    if (structureSet_.get() != NULL &&
+        GeometryToolbox::IsParallelOrOpposite(isOpposite,
+                                              viewportSlice.GetNormal(),
+                                              structureSet_->GetNormal()))
     {
-      NotifyLayerReady(new Renderer(structureSet_, viewportSlice), viewportSlice, false);
+      NotifyLayerReady(new Renderer(*structureSet_, viewportSlice), viewportSlice, false);
     }
   }
 }
--- a/Framework/Layers/DicomStructureSetRendererFactory.h	Fri Oct 06 17:25:08 2017 +0200
+++ b/Framework/Layers/DicomStructureSetRendererFactory.h	Sat Oct 07 13:11:12 2017 +0200
@@ -22,22 +22,33 @@
 #pragma once
 
 #include "../Toolbox/DicomStructureSet.h"
+#include "../Toolbox/IWebService.h"
 #include "LayerSourceBase.h"
 
 namespace OrthancStone
 {
-  class DicomStructureSetRendererFactory : public LayerSourceBase
+  class DicomStructureSetRendererFactory :
+    public LayerSourceBase,
+    private IWebService::ICallback
   {
   private:
     class Renderer;
+    class Operation;
 
-    DicomStructureSet&  structureSet_;
+    virtual void NotifyError(const std::string& uri,
+                             Orthanc::IDynamicObject* payload);
+
+    virtual void NotifySuccess(const std::string& uri,
+                               const void* answer,
+                               size_t answerSize,
+                               Orthanc::IDynamicObject* payload);
+
+    IWebService&                      orthanc_;
+    std::auto_ptr<DicomStructureSet>  structureSet_;
 
   public:
-    DicomStructureSetRendererFactory(DicomStructureSet& structureSet) :
-      structureSet_(structureSet)
-    {
-    }
+    DicomStructureSetRendererFactory(IWebService& orthanc,
+                                     const std::string& instance);
 
     virtual bool GetExtent(std::vector<Vector>& points,
                            const CoordinateSystem3D& viewportSlice)
--- a/Platforms/Generic/WebServiceGetCommand.cpp	Fri Oct 06 17:25:08 2017 +0200
+++ b/Platforms/Generic/WebServiceGetCommand.cpp	Sat Oct 07 13:11:12 2017 +0200
@@ -40,6 +40,7 @@
   void WebServiceGetCommand::Execute()
   {
     Orthanc::HttpClient client(parameters_, uri_);
+    client.SetTimeout(60);
     client.SetMethod(Orthanc::HttpMethod_Get);
     success_ = client.Apply(answer_);
   }
--- a/Platforms/Generic/WebServicePostCommand.cpp	Fri Oct 06 17:25:08 2017 +0200
+++ b/Platforms/Generic/WebServicePostCommand.cpp	Sat Oct 07 13:11:12 2017 +0200
@@ -41,6 +41,7 @@
   void WebServicePostCommand::Execute()
   {
     Orthanc::HttpClient client(parameters_, uri_);
+    client.SetTimeout(60);
     client.SetMethod(Orthanc::HttpMethod_Post);
     client.GetBody().swap(body_);
     success_ = client.Apply(answer_);