changeset 1631:960bb5fcc440

SortedFrames::GetFrameGeometry()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 09 Nov 2020 18:49:08 +0100
parents 78509230f0d7
children 9a4c09361f3e
files OrthancStone/Sources/Toolbox/SortedFrames.cpp OrthancStone/Sources/Toolbox/SortedFrames.h UnitTestsSources/SortedFramesTests.cpp
diffstat 3 files changed, 126 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancStone/Sources/Toolbox/SortedFrames.cpp	Mon Nov 09 18:01:32 2020 +0100
+++ b/OrthancStone/Sources/Toolbox/SortedFrames.cpp	Mon Nov 09 18:49:08 2020 +0100
@@ -24,6 +24,7 @@
 
 #include "GeometryToolbox.h"
 
+#include <Logging.h>
 #include <OrthancException.h>
 #include <Toolbox.h>
 
@@ -40,7 +41,8 @@
     }
 
     uint32_t tmp;
-    if (tags.ParseUnsignedInteger32(tmp, Orthanc::DICOM_TAG_NUMBER_OF_FRAMES))
+    if (tags.ParseUnsignedInteger32(tmp, Orthanc::DICOM_TAG_NUMBER_OF_FRAMES) &&
+        tmp > 0)
     {
       numberOfFrames_ = tmp;
     }
@@ -59,9 +61,68 @@
     {
       monochrome1_ = false;
     }
+
+    bool ok = false;
+
+    if (numberOfFrames_ > 1)
+    {
+      std::string offsets, increment;
+      if (tags.LookupStringValue(offsets, Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR, false) &&
+          tags.LookupStringValue(increment, Orthanc::DICOM_TAG_FRAME_INCREMENT_POINTER, false))
+      {
+        Orthanc::Toolbox::ToUpperCase(increment);
+        if (increment != "3004,000C")
+        {
+          LOG(WARNING) << "Bad value for the FrameIncrementPointer tags in a multiframe image";
+        }
+        else if (LinearAlgebra::ParseVector(frameOffsets_, offsets))
+        {
+          if (frameOffsets_.size() == numberOfFrames_)
+          {
+            ok = true;
+          }
+          else
+          {
+            LOG(WARNING) << "The size of the GridFrameOffsetVector does not correspond to the number of frames";
+          }
+        }
+        else
+        {
+          LOG(WARNING) << "Cannot parse the GridFrameOffsetVector tag";
+        }
+      }
+      else
+      {
+        LOG(INFO) << "Missing the frame offset information in a multiframe image";
+      }
+    }
+
+    if (!ok)
+    {
+      frameOffsets_.resize(numberOfFrames_);
+      for (size_t i = 0; i < numberOfFrames_; i++)
+      {
+        frameOffsets_[i] = 0;
+      }
+    }
   }
 
 
+  double SortedFrames::Instance::GetFrameOffset(unsigned int frame) const
+  {
+    assert(GetNumberOfFrames() == frameOffsets_.size());
+    
+    if (frame >= GetNumberOfFrames())
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+    }
+    else
+    {
+      return frameOffsets_[frame];
+    }
+  }
+  
+
   SortedFrames::Frame::Frame(const Instance& instance,
                              unsigned int frameNumber) :
     instance_(&instance),
@@ -364,6 +425,24 @@
   }
 
 
+  CoordinateSystem3D SortedFrames::GetFrameGeometry(size_t frameIndex) const
+  {
+    const Frame& frame = GetFrame(frameIndex);
+    CoordinateSystem3D geometry = frame.GetInstance().GetGeometry();
+
+    if (geometry.IsValid())
+    {
+      geometry.SetOrigin(geometry.GetOrigin() + geometry.GetNormal() *
+                         frame.GetInstance().GetFrameOffset(frame.GetFrameNumberInInstance()));
+      return geometry;
+    }
+    else
+    {
+      return geometry;
+    }
+  }
+
+
   bool SortedFrames::LookupFrame(size_t& frameIndex,
                                  const std::string& sopInstanceUid,
                                  unsigned int frameNumber) const
--- a/OrthancStone/Sources/Toolbox/SortedFrames.h	Mon Nov 09 18:01:32 2020 +0100
+++ b/OrthancStone/Sources/Toolbox/SortedFrames.h	Mon Nov 09 18:49:08 2020 +0100
@@ -38,6 +38,7 @@
       unsigned int        numberOfFrames_;
       CoordinateSystem3D  geometry_;
       bool                monochrome1_;
+      Vector              frameOffsets_;
 
     public:
       explicit Instance(const Orthanc::DicomMap& tags);
@@ -66,6 +67,8 @@
       {
         return monochrome1_;
       }
+
+      double GetFrameOffset(unsigned int frame) const;
     };
 
     struct Frame
@@ -199,6 +202,8 @@
       return GetFrame(frameIndex).GetInstance().IsMonochrome1();
     }
 
+    CoordinateSystem3D GetFrameGeometry(size_t frameIndex) const;
+
     bool LookupFrame(size_t& frameIndex,
                      const std::string& sopInstanceUid,
                      unsigned int frameNumber) const;
--- a/UnitTestsSources/SortedFramesTests.cpp	Mon Nov 09 18:01:32 2020 +0100
+++ b/UnitTestsSources/SortedFramesTests.cpp	Mon Nov 09 18:49:08 2020 +0100
@@ -245,6 +245,47 @@
 }
 
 
+TEST(SortedFrames, FrameOffset)
+{
+  Orthanc::DicomMap tags;
+  tags.SetValue(Orthanc::DICOM_TAG_STUDY_INSTANCE_UID, "study", false);
+  tags.SetValue(Orthanc::DICOM_TAG_SERIES_INSTANCE_UID, "series", false);
+  tags.SetValue(Orthanc::DICOM_TAG_SOP_INSTANCE_UID, "1.2.276.0.7230010.3.1.4.296485376.1.1568899779.944133", false);
+  tags.SetValue(Orthanc::DICOM_TAG_IMAGE_POSITION_PATIENT, "-350\\-145\\-985", false);
+  tags.SetValue(Orthanc::DICOM_TAG_IMAGE_ORIENTATION_PATIENT, "1\\0\\0\\0\\1\\0", false);
+  tags.SetValue(Orthanc::DICOM_TAG_NUMBER_OF_FRAMES, "2", false);
+
+  for (unsigned int i = 0; i < 3; i++)
+  {
+    tags.SetValue(Orthanc::DICOM_TAG_FRAME_INCREMENT_POINTER, i != 1 ? "3004,000c" : "nope", false);
+    tags.SetValue(Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR, i != 2 ? "8\\11" : "1\\2\\3", false);
+
+    OrthancStone::SortedFrames f;
+    f.AddInstance(tags);
+    f.Sort();
+
+    ASSERT_EQ(2u, f.GetFramesCount());
+    ASSERT_TRUE(f.GetFrameGeometry(0).IsValid());
+    ASSERT_TRUE(f.GetFrameGeometry(1).IsValid());
+    ASSERT_FLOAT_EQ(-350.0f, f.GetFrameGeometry(0).GetOrigin() [0]);
+    ASSERT_FLOAT_EQ(-145.0f, f.GetFrameGeometry(0).GetOrigin() [1]);
+    ASSERT_FLOAT_EQ(-350.0f, f.GetFrameGeometry(1).GetOrigin() [0]);
+    ASSERT_FLOAT_EQ(-145.0f, f.GetFrameGeometry(1).GetOrigin() [1]);
+
+    if (i == 0)
+    {
+      ASSERT_FLOAT_EQ(-985.0f + 8.0f, f.GetFrameGeometry(0).GetOrigin() [2]);
+      ASSERT_FLOAT_EQ(-985.0f + 11.0f, f.GetFrameGeometry(1).GetOrigin() [2]);
+    }
+    else
+    {
+      ASSERT_FLOAT_EQ(-985.0f, f.GetFrameGeometry(0).GetOrigin() [2]);
+      ASSERT_FLOAT_EQ(-985.0f, f.GetFrameGeometry(1).GetOrigin() [2]);
+    }
+  }
+}
+
+
 TEST(SortedFrames, Knix)  // Created using "SortedFramesCreateTest.py"
 {
   Orthanc::DicomMap tags;