changeset 1602:b2941196cabf

SortedFrames::LookupFrame()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 28 Oct 2020 16:35:45 +0100
parents 1704341bb96e
children 595c0952ef7e
files OrthancStone/Sources/Toolbox/SortedFrames.cpp OrthancStone/Sources/Toolbox/SortedFrames.h UnitTestsSources/SortedFramesTests.cpp
diffstat 3 files changed, 89 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancStone/Sources/Toolbox/SortedFrames.cpp	Wed Oct 28 15:46:25 2020 +0100
+++ b/OrthancStone/Sources/Toolbox/SortedFrames.cpp	Wed Oct 28 16:35:45 2020 +0100
@@ -144,10 +144,13 @@
       delete instances_[i];
     }
 
-    instancesIndex_.clear();
     studyInstanceUid_.clear();
     seriesInstanceUid_.clear();
     frames_.clear();
+
+    instancesIndex_.clear();
+    framesIndex_.clear();
+
     sorted_ = true;
   }
 
@@ -218,6 +221,7 @@
     
     for (unsigned int i = 0; i < instance.GetNumberOfFrames(); i++)
     {
+      framesIndex_[std::make_pair(instance.GetSopInstanceUid(), i)] = frames_.size();      
       frames_.push_back(Frame(instance, i));
     }
 
@@ -390,6 +394,33 @@
   }
 
 
+  bool SortedFrames::LookupFrame(size_t& frameIndex,
+                                 const std::string& sopInstanceUid,
+                                 unsigned int frameNumber) const
+  {
+    if (sorted_)
+    {
+      FramesIndex::const_iterator found = framesIndex_.find(
+        std::make_pair(sopInstanceUid, frameNumber));
+      
+      if (found == framesIndex_.end())
+      {
+        return false;
+      }
+      else
+      {
+        frameIndex = found->second;
+        return true;
+      }      
+    }
+    else
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls,
+                                      "Sort() has not been called");
+    }
+  }
+  
+
   void SortedFrames::Sort()
   {
     if (!sorted_)
@@ -407,6 +438,7 @@
 
       frames_.clear();
       frames_.reserve(totalFrames);
+      framesIndex_.clear();
 
       SortUsingIntegerTag(remainingInstances, Orthanc::DICOM_TAG_INSTANCE_NUMBER);  // VR is "IS"
       SortUsingIntegerTag(remainingInstances, Orthanc::DICOM_TAG_IMAGE_INDEX);  // VR is "US"
--- a/OrthancStone/Sources/Toolbox/SortedFrames.h	Wed Oct 28 15:46:25 2020 +0100
+++ b/OrthancStone/Sources/Toolbox/SortedFrames.h	Wed Oct 28 16:35:45 2020 +0100
@@ -98,12 +98,17 @@
     // Maps "SOPInstanceUID" to an index in "instances_"
     typedef std::map<std::string, size_t>  InstancesIndex;
 
+    // Maps pair "(SOPInstanceUID, FrameNumber)" to an index in
+    // "frames_" (only once "Sort()" is called)
+    typedef std::map<std::pair<std::string, unsigned int>, size_t>  FramesIndex;
+
     std::string             studyInstanceUid_;
     std::string             seriesInstanceUid_;
     std::vector<Instance*>  instances_;
     std::vector<Frame>      frames_;
     bool                    sorted_;
     InstancesIndex          instancesIndex_;
+    FramesIndex             framesIndex_;
 
     const Instance& GetInstance(size_t instanceIndex) const;
 
@@ -194,6 +199,10 @@
       return GetFrame(frameIndex).GetInstance().IsMonochrome1();
     }
 
+    bool LookupFrame(size_t& frameIndex,
+                     const std::string& sopInstanceUid,
+                     unsigned int frameNumber) const;
+
     void Sort();
   };
 }
--- a/UnitTestsSources/SortedFramesTests.cpp	Wed Oct 28 15:46:25 2020 +0100
+++ b/UnitTestsSources/SortedFramesTests.cpp	Wed Oct 28 16:35:45 2020 +0100
@@ -94,11 +94,13 @@
   f.AddInstance(tags);
 
   size_t i;
+  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop3"));  ASSERT_EQ(0u, i);
   ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop1"));  ASSERT_EQ(1u, i);
   ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop2"));  ASSERT_EQ(2u, i);
-  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop3"));  ASSERT_EQ(0u, i);
   ASSERT_FALSE(f.LookupSopInstanceUid(i, "nope"));
-    
+
+  ASSERT_THROW(f.LookupFrame(i, "sop3", 0), Orthanc::OrthancException);  // Not sorted yet
+  
   f.Sort();
   ASSERT_EQ(3u, f.GetInstancesCount());
   ASSERT_EQ("sop3", f.GetSopInstanceUid(0));
@@ -117,6 +119,18 @@
   ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop2"));  ASSERT_EQ(2u, i);
   ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop3"));  ASSERT_EQ(0u, i);
   ASSERT_FALSE(f.LookupSopInstanceUid(i, "nope"));
+
+  ASSERT_TRUE(f.LookupFrame(i, "sop1", 0));  ASSERT_EQ(0u, i);
+  ASSERT_TRUE(f.LookupFrame(i, "sop1", 1));  ASSERT_EQ(1u, i);
+  ASSERT_TRUE(f.LookupFrame(i, "sop1", 2));  ASSERT_EQ(2u, i);
+  ASSERT_TRUE(f.LookupFrame(i, "sop2", 0));  ASSERT_EQ(3u, i);
+  ASSERT_TRUE(f.LookupFrame(i, "sop2", 1));  ASSERT_EQ(4u, i);
+  ASSERT_TRUE(f.LookupFrame(i, "sop3", 0));  ASSERT_EQ(5u, i);
+
+  ASSERT_FALSE(f.LookupFrame(i, "nope", 0));
+  ASSERT_FALSE(f.LookupFrame(i, "sop1", 3));
+  ASSERT_FALSE(f.LookupFrame(i, "sop2", 2));
+  ASSERT_FALSE(f.LookupFrame(i, "sop3", 1));
 }
 
 
@@ -146,6 +160,17 @@
   tags.SetValue(Orthanc::DICOM_TAG_INSTANCE_NUMBER, "10", false);
   f.AddInstance(tags);
     
+  size_t i;
+  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop1"));  ASSERT_EQ(0u, i);
+  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop2"));  ASSERT_EQ(1u, i);
+  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop2a")); ASSERT_EQ(2u, i);
+  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop4"));  ASSERT_EQ(3u, i);
+  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop3"));  ASSERT_EQ(4u, i);
+  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop5"));  ASSERT_EQ(5u, i);
+  ASSERT_FALSE(f.LookupSopInstanceUid(i, "nope"));
+
+  ASSERT_THROW(f.LookupFrame(i, "sop1", 0), Orthanc::OrthancException);  // Not sorted yet
+
   f.Sort();
   ASSERT_EQ(6u, f.GetInstancesCount());
   ASSERT_EQ("sop1", f.GetSopInstanceUid(0));
@@ -160,7 +185,26 @@
   ASSERT_EQ("sop4", f.GetFrameSopInstanceUid(2));  ASSERT_EQ(0u, f.GetFrameNumberInInstance(2));
   ASSERT_EQ("sop5", f.GetFrameSopInstanceUid(3));  ASSERT_EQ(0u, f.GetFrameNumberInInstance(3));
   ASSERT_EQ("sop1", f.GetFrameSopInstanceUid(4));  ASSERT_EQ(0u, f.GetFrameNumberInInstance(4));
-  ASSERT_EQ("sop2a", f.GetFrameSopInstanceUid(5));  ASSERT_EQ(0u, f.GetFrameNumberInInstance(5));
+  ASSERT_EQ("sop2a", f.GetFrameSopInstanceUid(5)); ASSERT_EQ(0u, f.GetFrameNumberInInstance(5));
+
+  // The instances must not have been reordered, only the frames
+  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop1"));  ASSERT_EQ(0u, i);
+  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop2"));  ASSERT_EQ(1u, i);
+  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop2a")); ASSERT_EQ(2u, i);
+  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop4"));  ASSERT_EQ(3u, i);
+  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop3"));  ASSERT_EQ(4u, i);
+  ASSERT_TRUE(f.LookupSopInstanceUid(i, "sop5"));  ASSERT_EQ(5u, i);
+  ASSERT_FALSE(f.LookupSopInstanceUid(i, "nope"));
+
+  ASSERT_TRUE(f.LookupFrame(i, "sop2", 0));  ASSERT_EQ(0u, i);
+  ASSERT_TRUE(f.LookupFrame(i, "sop3", 0));  ASSERT_EQ(1u, i);
+  ASSERT_TRUE(f.LookupFrame(i, "sop4", 0));  ASSERT_EQ(2u, i);
+  ASSERT_TRUE(f.LookupFrame(i, "sop5", 0));  ASSERT_EQ(3u, i);
+  ASSERT_TRUE(f.LookupFrame(i, "sop1", 0));  ASSERT_EQ(4u, i);
+  ASSERT_TRUE(f.LookupFrame(i, "sop2a", 0)); ASSERT_EQ(5u, i);
+
+  ASSERT_FALSE(f.LookupFrame(i, "nope", 0));
+  ASSERT_FALSE(f.LookupFrame(i, "sop1", 1));
 }