From 35d25a15a11b902c47d87cf51c9bcced92208a15 Mon Sep 17 00:00:00 2001
From: remicres <remi.cresson@teledetection.fr>
Date: Wed, 10 Aug 2016 09:50:59 +0000
Subject: [PATCH] FIX: Pierre code + itk::object inheritance implemented

---
 include/lsgrmController.h   | 177 +++++++++++++++++++++++-------------
 include/lsgrmController.txx | 163 ++++++++++++---------------------
 2 files changed, 171 insertions(+), 169 deletions(-)

diff --git a/include/lsgrmController.h b/include/lsgrmController.h
index d560f49..ef9dba7 100644
--- a/include/lsgrmController.h
+++ b/include/lsgrmController.h
@@ -3,74 +3,121 @@
 #include "lsrmGetInternalMemory.h"
 #include "lsgrmSplitter.h"
 #include "lsgrmGraphOperations.h"
+#include "itkObject.h"
 #include "itkMacro.h"
 
 namespace lsgrm
-{	
-	template<class TSegmenter>
-	class Controller
-	{
-	public:
-
-		/* Some convenient typedefs */
-		using SegmenterType = TSegmenter;
-		using ImageType = typename SegmenterType::ImageType;
-		using LabelImageType = typename SegmenterType::LabelImageType;
-		using SegmentationParameterType = typename SegmenterType::ParameterType;
-
-		/* Default constructor and destructor. */
-		Controller();
-		~Controller();
-
-		void RunSegmentation();
-
-		void SetImageDivision(bool f);
-		void SetInputImage(ImageType * inputImage);
-		void SetTemporaryDirectory(const std::string& str);
-		void SetTileWidth(const unsigned int v);
-		void SetTileHeight(const unsigned int v);
-        void SetNumberOfFirstIterations(const unsigned int v);
-        void SetNumberOfIterations(const unsigned int v);
-		void SetSpecificParameters(const SegmentationParameterType& params);
-		void SetThreshold(const float& t);
-		void SetInternalMemoryAvailable(long long unsigned int v); // expecting a value in Mbytes.
-		void SetAutomaticTilingLayout(bool value);
-		
-		typename LabelImageType::Pointer GetLabeledClusteredOutput();
-
-		itkGetMacro(ListOfTemporaryFiles, std::vector<std::string>);
-
-	private:
-
-		void GetAutomaticConfiguration();
-		long unsigned int GetMaximumNumberOfNodesInMemory();
-
-		/* Parameters given by the user */
-		long long unsigned int m_Memory; // RAM available for the computation.
-		ImageType * m_InputImage; // Input image
-		std::string m_TemporaryDirectory; // Directory used to store intermediate files during the process.
-		bool m_ImageDivisionActivated; // The input image must be divided.
-		bool m_CleanTemporaryDirectory; // Clean the temporary directory.
-
-		/* Specific segmentation parameters */
-		SegmentationParameterType m_SpecificParameters;
-		float m_Threshold;
-
-		/* Internal attribute members.*/
-		unsigned int m_NbTilesX;
-		unsigned int m_NbTilesY;
-        unsigned int m_NumberOfFirstIterations;
-        unsigned int m_NumberOfIterations;
-		unsigned int m_Margin;
-		unsigned int m_TileWidth;
-		unsigned int m_TileHeight;
-		bool m_AutomaticTilingLayout;
-
-		std::vector<ProcessingTile> m_Tiles;
-		std::vector<std::string> m_ListOfTemporaryFiles;
-
-		typename LabelImageType::Pointer m_LabelImage;
-	};
+{
+template<class TSegmenter>
+class ITK_EXPORT Controller : public itk::Object
+{
+public:
+
+  /** Standard class typedef */
+  typedef Controller Self;
+  typedef itk::LightObject                     Superclass;
+  typedef itk::SmartPointer<Self>              Pointer;
+  typedef itk::SmartPointer<const Self>        ConstPointer;
+
+  /** Runtime information support. */
+  itkTypeMacro(Controller, itk::Object);
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Enum for tiling mode */
+  enum LSGRMTilingMode
+    {
+    LSGRM_TILING_NONE,
+    LSGRM_TILING_USER,
+    LSGRM_TILING_AUTO
+    };
+
+  /* Some convenient typedefs */
+  using SegmenterType = TSegmenter;
+  using ImageType = typename SegmenterType::ImageType;
+  using LabelImageType = typename SegmenterType::LabelImageType;
+  using SegmentationParameterType = typename SegmenterType::ParameterType;
+
+  /* Default constructor and destructor. */
+  Controller();
+  ~Controller();
+
+  void RunSegmentation();
+
+  void SetSpecificParameters(const SegmentationParameterType& params);
+  void SetInputImage(ImageType * inputImage);
+  void SetInternalMemoryAvailable(long long unsigned int v); // expecting a value in Mbytes.
+
+  /* Accessors */
+  void SetTilingModeNone(){m_TilingMode = LSGRM_TILING_NONE;};
+  void SetTilingModeUser(){m_TilingMode = LSGRM_TILING_USER;};
+  void SetTilingModeAuto(){m_TilingMode = LSGRM_TILING_AUTO;};
+
+  typename LabelImageType::Pointer GetLabeledClusteredOutput();
+
+  itkGetMacro(Margin, unsigned int);
+  itkGetMacro(TemporaryFilesList, std::vector<std::string>);
+
+  itkGetMacro(CleanTemporaryDirectory, bool);
+  itkSetMacro(CleanTemporaryDirectory, bool);
+
+  itkGetMacro(TemporaryDirectory, std::string);
+  itkSetMacro(TemporaryDirectory, std::string);
+
+  itkGetMacro(Threshold, float);
+  itkSetMacro(Threshold, float);
+
+  itkGetMacro(NumberOfIterations, unsigned int);
+  itkSetMacro(NumberOfIterations, unsigned int);
+
+  itkGetMacro(NbTilesX, unsigned int);
+  itkSetMacro(NbTilesX, unsigned int);
+
+  itkGetMacro(NbTilesY, unsigned int);
+  itkSetMacro(NbTilesY, unsigned int);
+
+  itkGetMacro(NumberOfFirstIterations, unsigned int);
+  itkSetMacro(NumberOfFirstIterations, unsigned int);
+
+  itkGetMacro(TileWidth, unsigned int);
+  itkSetMacro(TileWidth, unsigned int);
+
+  itkGetMacro(TileHeight, unsigned int);
+  itkSetMacro(TileHeight, unsigned int);
+
+private:
+
+  void GetAutomaticConfiguration();
+  long unsigned int GetMaximumNumberOfNodesInMemory();
+
+  /* Parameters given by the user */
+  std::string m_TemporaryDirectory;      // Directory used to store intermediate files during the process.
+  bool        m_CleanTemporaryDirectory; // Clean the temporary directory.
+  ImageType * m_InputImage;              // Input image
+
+  /* Segmentation parameters */
+  SegmentationParameterType m_SpecificParameters; // Specific parameters
+  float                     m_Threshold;          // Threshold
+  unsigned int              m_NumberOfIterations; // Number of iterations
+
+  /* Parameters given by the user or computed automatically
+   * depending of the chosen mode
+   */
+  long long unsigned int m_Memory; // RAM available for the computation.
+  unsigned int m_NbTilesX;
+  unsigned int m_NbTilesY;
+  unsigned int m_NumberOfFirstIterations;
+  unsigned int m_TileWidth;
+  unsigned int m_TileHeight;
+
+  /* read-only variables */
+  unsigned int m_Margin;
+  std::vector<ProcessingTile> m_Tiles;
+  std::vector<std::string> m_TemporaryFilesList;
+  LSGRMTilingMode m_TilingMode;
+  typename LabelImageType::Pointer m_LabelImage;
+};
 } // end of namespace lsgrm
 
 #include "lsgrmController.txx"
diff --git a/include/lsgrmController.txx b/include/lsgrmController.txx
index ba55f0f..a1da11d 100644
--- a/include/lsgrmController.txx
+++ b/include/lsgrmController.txx
@@ -6,8 +6,7 @@ namespace lsgrm
 template<class TSegmenter>
 Controller<TSegmenter>::Controller()
 {
-  m_Memory = 0;
-  m_ImageDivisionActivated = true;
+  m_TilingMode = LSGRM_TILING_AUTO;
 }
 
 template<class TSegmenter>
@@ -19,22 +18,29 @@ template<class TSegmenter>
 void Controller<TSegmenter>::RunSegmentation()
 {
 
-  // TODO: smarter value?
-  const unsigned int numberOfIterationsForPartialSegmentations = 3;
-  unsigned int numberOfIterations = m_NumberOfIterations;
-
-  // Automatic procedure
-  if(m_Memory == 0)
-    {
-    this->GetAutomaticConfiguration();
-    }
-  else
+  if (m_TilingMode == LSGRM_TILING_AUTO || m_TilingMode == LSGRM_TILING_USER)
     {
-    m_Margin = static_cast<unsigned int>(pow(2, m_NumberOfFirstIterations + 1) - 2);
-    }
+    // TODO: smarter value?
+    const unsigned int numberOfIterationsForPartialSegmentations = 3;
+    unsigned int numberOfIterations = m_NumberOfIterations;
+
+    if(m_TilingMode == LSGRM_TILING_AUTO)
+      {
+      this->GetAutomaticConfiguration();
+      }
+    else if (m_TilingMode == LSGRM_TILING_USER)
+      {
+      m_Margin = static_cast<unsigned int>(pow(2, m_NumberOfFirstIterations + 1) - 2);
+      }
+
+    std::cout <<
+        "--- Configuration: \n" <<
+        "\tAvailable RAM: " << m_Memory << "\n" <<
+        "\tInput image dimensions: " << m_InputImage->GetLargestPossibleRegion().GetSize() << "\n" <<
+        "\tNumber of first iterations: " << m_NumberOfFirstIterations << "\n" <<
+        "\tStability margin: " << m_Margin << "\n" <<
+        "\tComputed tile size: " << m_TileWidth << " x " << m_TileHeight << std::endl;
 
-  if(m_ImageDivisionActivated)
-    {
     // Compute the splitting scheme
     SplitOTBImage<ImageType>(m_InputImage, m_TileWidth, m_TileHeight, m_Margin,
         m_NbTilesX, m_NbTilesY, m_Tiles);
@@ -115,20 +121,20 @@ void Controller<TSegmenter>::RunSegmentation()
           m_InputImage->GetNumberOfComponentsPerPixel(),
           numberOfIterations);
 
-      //      ShowTime(t);
+      ShowTime(t);
 
       }
-    else
+    else // accumulatedMemory > m_Memory
       {
       // That means there are no more possible fusions but we can not store the output graph
       // Todo do not clean up temporary directory before copying resulting graph to the output directory
       // In the output directory add an info file to give the number of tiles.
+      itkExceptionMacro(<< "No more possible fusions, but can not store the output graph");
       }
-
     }
-  else
+  else // tiling_mode is none
     {
-    //TODO: use classic GRM
+    // todo use classic grm
     }
 
 
@@ -158,6 +164,12 @@ long unsigned int Controller<TSegmenter>::GetMaximumNumberOfNodesInMemory()
 
 }
 
+/*
+ * Compute a tiling layout such as tiles respect following constraints,
+ * sorted by priority:
+ * 1.number of nodes in a regular tile should fit the available memory
+ * 2.regular tiles compactness must be the smallest
+ */
 template<class TSegmenter>
 void Controller<TSegmenter>::GetAutomaticConfiguration()
 {
@@ -169,7 +181,7 @@ void Controller<TSegmenter>::GetAutomaticConfiguration()
   // (assuming that maxMargin = tileDimension/2)
   maximumNumberOfNodesInMemory /= 4;
 
-  // Find the largest tile with the lowest compactness
+  // Find the largest tile size
   const unsigned int imageWidth = m_InputImage->GetLargestPossibleRegion().GetSize()[0];
   const unsigned int imageHeight = m_InputImage->GetLargestPossibleRegion().GetSize()[1];
   unsigned int nbOfTiles = 1; // total number of tiles
@@ -179,32 +191,34 @@ void Controller<TSegmenter>::GetAutomaticConfiguration()
   unsigned int tileWidth(0), tileHeight(0);
   while( nbOfNodesInImage / ((float) nbOfTiles) > maximumNumberOfNodesInMemory)
     {
-    // Get the multiples of k. For each one, compute the
-    // layout which has the minimum tile compactness
-    float lowestCompactness = itk::NumericTraits<float>::max();
-    for (unsigned int layoutNCol = 1; layoutNCol<=nbOfTiles; layoutNCol++)
+    nbOfTiles++;
+    }
+  nbOfTiles--;
+
+  // Get the multiples of k. For each one, compute the
+  // layout which has the minimum tile compactness
+  float lowestCompactness = itk::NumericTraits<float>::max();
+  for (unsigned int layoutNCol = 1; layoutNCol<=nbOfTiles; layoutNCol++)
+    {
+    if (nbOfTiles % layoutNCol == 0)      // Is it a multiple of the nb of Tiles?
       {
-      if (nbOfTiles % layoutNCol == 0)      // Is it a multiple of the nb of Tiles?
+      // Compute tile compactness
+      unsigned int layoutNRow = nbOfTiles / layoutNCol;
+      tileWidth = imageWidth / layoutNCol;
+      tileHeight = imageHeight / layoutNRow;
+      float perimeter = tileWidth + tileHeight;
+      float surface = tileWidth * tileHeight;
+      float compactness = perimeter / surface;
+
+      // Update minimum compactness
+      if (lowestCompactness > compactness)
         {
-        // Compute tile compactness
-        unsigned int layoutNRow = nbOfTiles / layoutNCol;
-        tileWidth = imageWidth / layoutNCol;
-        tileHeight = imageHeight / layoutNRow;
-        float perimeter = tileWidth + tileHeight;
-        float surface = tileWidth * tileHeight;
-        float compactness = perimeter / surface;
-
-        // Update minimum compactness
-        if (lowestCompactness > compactness)
-          {
-          lowestCompactness = compactness;
-          m_NbTilesX = layoutNCol;
-          m_NbTilesY = layoutNRow;
-          }
+        lowestCompactness = compactness;
+        m_NbTilesX = layoutNCol;
+        m_NbTilesY = layoutNRow;
         }
-      } // for each multiple of k
-    nbOfTiles++;
-    } // while
+      }
+    } // for each multiple of k
 
   // Compute the tile size
   m_TileWidth = static_cast<unsigned int>(imageWidth/m_NbTilesX);
@@ -227,22 +241,6 @@ void Controller<TSegmenter>::GetAutomaticConfiguration()
   m_Margin = prevMargin;
   m_NumberOfFirstIterations = niter - 1;
 
-  std::cout <<
-      "--- Configuration: \n" <<
-      "\tAvailable RAM: " << m_Memory << "\n" <<
-      "\tInput image dimensions: " << imageWidth << " x " << imageHeight << "\n" <<
-      "\tMaximum number of nodes in memory: " << maximumNumberOfNodesInMemory << "\n" <<
-      "\tOptimal square tile size: " << tileDimension << "\n" <<
-      "\tNumber of first iterations: " << niter << "\n" <<
-      "\tStability margin: " << prevMargin << "\n" <<
-      "\tComputed tile size: " << m_TileWidth << " x " << m_TileHeight << std::endl;
-
-}
-
-template <class TSegmenter>
-void Controller<TSegmenter>::SetTemporaryDirectory(const std::string& str)
-{
-  m_TemporaryDirectory = str;
 }
 
 template <class TSegmenter>
@@ -252,61 +250,18 @@ void Controller<TSegmenter>::SetInternalMemoryAvailable(long long unsigned int v
   m_Memory = v * 1024ul * 1024ul;
 }
 
-template<class TSegmenter>
-void Controller<TSegmenter>::SetImageDivision(bool f)
-{
-  m_ImageDivisionActivated = f;
-}
-
-template<class TSegmenter>
-void Controller<TSegmenter>::SetAutomaticTilingLayout(bool value)
-{
-  m_AutomaticTilingLayout = value;
-}
-
 template<class TSegmenter>
 void Controller<TSegmenter>::SetInputImage(ImageType * inputImage)
 {
   m_InputImage = inputImage;
 }
 
-template<class TSegmenter>
-void Controller<TSegmenter>::SetTileWidth(const unsigned int v)
-{
-  m_TileWidth = v;
-}
-
-template<class TSegmenter>
-void Controller<TSegmenter>::SetTileHeight(const unsigned int v)
-{
-  m_TileHeight = v;
-}
-
-template<class TSegmenter>
-void Controller<TSegmenter>::SetNumberOfFirstIterations(const unsigned int v)
-{
-  m_NumberOfFirstIterations = v;
-  m_Margin = static_cast<unsigned int>(pow(2, m_NumberOfFirstIterations + 1) - 2);// 2^{n+1}-2
-}
-
-template<class TSegmenter>
-void Controller<TSegmenter>::SetNumberOfIterations(const unsigned int v)
-{
-  m_NumberOfIterations = v;
-}
-
 template<class TSegmenter>
 void Controller<TSegmenter>::SetSpecificParameters(const SegmentationParameterType& params)
 {
   m_SpecificParameters = params;
 }
 
-template<class TSegmenter>
-void Controller<TSegmenter>::SetThreshold(const float& t)
-{
-  m_Threshold = t;
-}
-
 template<class TSegmenter>
 typename Controller<TSegmenter>::LabelImageType::Pointer
 Controller<TSegmenter>::GetLabeledClusteredOutput()
-- 
GitLab