diff Framework/Toolbox/DicomStructureSet.cpp @ 860:238693c3bc51 am-dev

merge default -> am-dev
author Alain Mazy <alain@mazy.be>
date Mon, 24 Jun 2019 14:35:00 +0200
parents 266e2b0b9abc
children 32eaf4929b08
line wrap: on
line diff
--- a/Framework/Toolbox/DicomStructureSet.cpp	Wed Jun 19 17:36:33 2019 +0200
+++ b/Framework/Toolbox/DicomStructureSet.cpp	Mon Jun 24 14:35:00 2019 +0200
@@ -22,7 +22,6 @@
 #include "DicomStructureSet.h"
 
 #include "../Toolbox/GeometryToolbox.h"
-#include "../Toolbox/MessagingToolbox.h"
 
 #include <Core/Logging.h>
 #include <Core/OrthancException.h>
@@ -31,7 +30,6 @@
 
 #include <limits>
 #include <stdio.h>
-#include <boost/lexical_cast.hpp>
 #include <boost/geometry.hpp>
 #include <boost/geometry/geometries/point_xy.hpp>
 #include <boost/geometry/geometries/polygon.hpp>
@@ -367,9 +365,7 @@
 
   DicomStructureSet::DicomStructureSet(const OrthancPlugins::FullOrthancDataset& tags)
   {
-    using namespace OrthancPlugins;
-
-    DicomDatasetReader reader(tags);
+    OrthancPlugins::DicomDatasetReader reader(tags);
     
     size_t count, tmp;
     if (!tags.GetSequenceSize(count, DICOM_TAG_RT_ROI_OBSERVATIONS_SEQUENCE) ||
@@ -385,18 +381,18 @@
     for (size_t i = 0; i < count; i++)
     {
       structures_[i].interpretation_ = reader.GetStringValue
-        (DicomPath(DICOM_TAG_RT_ROI_OBSERVATIONS_SEQUENCE, i,
-                   DICOM_TAG_RT_ROI_INTERPRETED_TYPE),
+        (OrthancPlugins::DicomPath(DICOM_TAG_RT_ROI_OBSERVATIONS_SEQUENCE, i,
+                                   DICOM_TAG_RT_ROI_INTERPRETED_TYPE),
          "No interpretation");
 
       structures_[i].name_ = reader.GetStringValue
-        (DicomPath(DICOM_TAG_STRUCTURE_SET_ROI_SEQUENCE, i,
-                   DICOM_TAG_ROI_NAME),
+        (OrthancPlugins::DicomPath(DICOM_TAG_STRUCTURE_SET_ROI_SEQUENCE, i,
+                                   DICOM_TAG_ROI_NAME),
          "No interpretation");
 
       Vector color;
-      if (ParseVector(color, tags, DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
-                                             DICOM_TAG_ROI_DISPLAY_COLOR)) &&
+      if (ParseVector(color, tags, OrthancPlugins::DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
+                                                             DICOM_TAG_ROI_DISPLAY_COLOR)) &&
           color.size() == 3)
       {
         structures_[i].red_ = ConvertColor(color[0]);
@@ -411,37 +407,55 @@
       }
 
       size_t countSlices;
-      if (!tags.GetSequenceSize(countSlices, DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
-                                                       DICOM_TAG_CONTOUR_SEQUENCE)))
+      if (!tags.GetSequenceSize(countSlices, OrthancPlugins::DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
+                                                                       DICOM_TAG_CONTOUR_SEQUENCE)))
       {
         countSlices = 0;
       }
 
-      LOG(WARNING) << "New RT structure: \"" << structures_[i].name_ 
+      LOG(INFO) << "New RT structure: \"" << structures_[i].name_ 
                    << "\" with interpretation \"" << structures_[i].interpretation_
                    << "\" containing " << countSlices << " slices (color: " 
                    << static_cast<int>(structures_[i].red_) << "," 
                    << static_cast<int>(structures_[i].green_) << ","
                    << static_cast<int>(structures_[i].blue_) << ")";
 
+      // These temporary variables avoid allocating many vectors in the loop below
+      OrthancPlugins::DicomPath countPointsPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
+                                                DICOM_TAG_CONTOUR_SEQUENCE, 0,
+                                                DICOM_TAG_NUMBER_OF_CONTOUR_POINTS);
+
+      OrthancPlugins::DicomPath geometricTypePath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
+                                                  DICOM_TAG_CONTOUR_SEQUENCE, 0,
+                                                  DICOM_TAG_CONTOUR_GEOMETRIC_TYPE);
+      
+      OrthancPlugins::DicomPath imageSequencePath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
+                                                  DICOM_TAG_CONTOUR_SEQUENCE, 0,
+                                                  DICOM_TAG_CONTOUR_IMAGE_SEQUENCE);
+
+      OrthancPlugins::DicomPath referencedInstancePath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
+                                                       DICOM_TAG_CONTOUR_SEQUENCE, 0,
+                                                       DICOM_TAG_CONTOUR_IMAGE_SEQUENCE, 0,
+                                                       DICOM_TAG_REFERENCED_SOP_INSTANCE_UID);
+
+      OrthancPlugins::DicomPath contourDataPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
+                                                DICOM_TAG_CONTOUR_SEQUENCE, 0,
+                                                DICOM_TAG_CONTOUR_DATA);
+
       for (size_t j = 0; j < countSlices; j++)
       {
         unsigned int countPoints;
 
-        if (!reader.GetUnsignedIntegerValue
-            (countPoints, DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
-                                    DICOM_TAG_CONTOUR_SEQUENCE, j,
-                                    DICOM_TAG_NUMBER_OF_CONTOUR_POINTS)))
+        countPointsPath.SetPrefixIndex(1, j);
+        if (!reader.GetUnsignedIntegerValue(countPoints, countPointsPath))
         {
           throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
         }
             
         //LOG(INFO) << "Parsing slice containing " << countPoints << " vertices";
 
-        std::string type = reader.GetMandatoryStringValue
-          (DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
-                     DICOM_TAG_CONTOUR_SEQUENCE, j,
-                     DICOM_TAG_CONTOUR_GEOMETRIC_TYPE));
+        geometricTypePath.SetPrefixIndex(1, j);
+        std::string type = reader.GetMandatoryStringValue(geometricTypePath);
         if (type != "CLOSED_PLANAR")
         {
           LOG(WARNING) << "Ignoring contour with geometry type: " << type;
@@ -449,24 +463,19 @@
         }
 
         size_t size;
-        if (!tags.GetSequenceSize(size, DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
-                                                  DICOM_TAG_CONTOUR_SEQUENCE, j,
-                                                  DICOM_TAG_CONTOUR_IMAGE_SEQUENCE)) ||
+
+        imageSequencePath.SetPrefixIndex(1, j);
+        if (!tags.GetSequenceSize(size, imageSequencePath) ||
             size != 1)
         {
           throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);          
         }
 
-        std::string sopInstanceUid = reader.GetMandatoryStringValue
-          (DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
-                     DICOM_TAG_CONTOUR_SEQUENCE, j,
-                     DICOM_TAG_CONTOUR_IMAGE_SEQUENCE, 0,
-                     DICOM_TAG_REFERENCED_SOP_INSTANCE_UID));
-        
-        std::string slicesData = reader.GetMandatoryStringValue
-          (DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
-                     DICOM_TAG_CONTOUR_SEQUENCE, j,
-                     DICOM_TAG_CONTOUR_DATA));
+        referencedInstancePath.SetPrefixIndex(1, j);
+        std::string sopInstanceUid = reader.GetMandatoryStringValue(referencedInstancePath);
+
+        contourDataPath.SetPrefixIndex(1, j);        
+        std::string slicesData = reader.GetMandatoryStringValue(contourDataPath);
 
         Vector points;
         if (!LinearAlgebra::ParseVector(points, slicesData) ||
@@ -531,6 +540,13 @@
   }
 
 
+  Color DicomStructureSet::GetStructureColor(size_t index) const
+  {
+    const Structure& s = GetStructure(index);
+    return Color(s.red_, s.green_, s.blue_);
+  }
+  
+    
   void DicomStructureSet::GetStructureColor(uint8_t& red,
                                             uint8_t& green,
                                             uint8_t& blue,
@@ -668,50 +684,9 @@
   }
 
   
-  DicomStructureSet* DicomStructureSet::SynchronousLoad(OrthancPlugins::IOrthancConnection& orthanc,
-                                                        const std::string& instanceId)
-  {
-    const std::string uri = "/instances/" + instanceId + "/tags?ignore-length=3006-0050";
-    OrthancPlugins::FullOrthancDataset dataset(orthanc, uri);
-
-    std::auto_ptr<DicomStructureSet> result(new DicomStructureSet(dataset));
-
-    std::set<std::string> instances;
-    result->GetReferencedInstances(instances);
-
-    for (std::set<std::string>::const_iterator it = instances.begin();
-         it != instances.end(); ++it)
-    {
-      Json::Value lookup;
-      MessagingToolbox::RestApiPost(lookup, orthanc, "/tools/lookup", *it);
-
-      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_UnknownResource);          
-      }
-
-      OrthancPlugins::FullOrthancDataset slice
-        (orthanc, "/instances/" + lookup[0]["ID"].asString() + "/tags");
-      Orthanc::DicomMap m;
-      MessagingToolbox::ConvertDataset(m, slice);
-      result->AddReferencedSlice(m);
-    }
-
-    result->CheckReferencedSlices();
-
-    return result.release();
-  }
-
-
   bool DicomStructureSet::ProjectStructure(std::vector< std::vector<PolygonPoint> >& polygons,
-                                           Structure& structure,
-                                           const CoordinateSystem3D& slice)
+                                           const Structure& structure,
+                                           const CoordinateSystem3D& slice) const
   {
     polygons.clear();
 
@@ -722,7 +697,7 @@
     {
       // This is an axial projection
 
-      for (Polygons::iterator polygon = structure.polygons_.begin();
+      for (Polygons::const_iterator polygon = structure.polygons_.begin();
            polygon != structure.polygons_.end(); ++polygon)
       {
         if (polygon->IsOnSlice(slice))
@@ -748,7 +723,7 @@
       // Sagittal or coronal projection
       std::vector<BoostPolygon> projected;
   
-      for (Polygons::iterator polygon = structure.polygons_.begin();
+      for (Polygons::const_iterator polygon = structure.polygons_.begin();
            polygon != structure.polygons_.end(); ++polygon)
       {
         double x1, y1, x2, y2;