diff --git a/include/lsgrmController.h b/include/lsgrmController.h
index afaba38389be0be222023eb92da2b992f1367f44..5da2eb68079292c37a9878259ca93422930b5212 100644
--- a/include/lsgrmController.h
+++ b/include/lsgrmController.h
@@ -49,13 +49,12 @@ public:
   typename LabelImageType::Pointer GetLabeledClusteredOutput();
 
   itkGetMacro(Margin, unsigned int);
-  itkGetMacro(TemporaryFilesList, std::vector<std::string>);
 
-  itkGetMacro(CleanTemporaryDirectory, bool);
-  itkSetMacro(CleanTemporaryDirectory, bool);
+  itkGetMacro(CleanTemporaryFiles, bool);
+  itkSetMacro(CleanTemporaryFiles, bool);
 
-  itkGetMacro(TemporaryDirectory, std::string);
-  itkSetMacro(TemporaryDirectory, std::string);
+  itkGetMacro(TemporaryFilesPrefix, std::string);
+  itkSetMacro(TemporaryFilesPrefix, std::string);
 
   itkGetMacro(Threshold, float);
   itkSetMacro(Threshold, float);
@@ -94,8 +93,8 @@ private:
   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.
+  std::string m_TemporaryFilesPrefix;    // Path used to store intermediate files during the process.
+  bool        m_CleanTemporaryFiles;     // Clean temporary files
   ImageType * m_InputImage;              // Input image
 
   /* Segmentation parameters */
@@ -117,7 +116,6 @@ private:
   LSGRMTilingMode                    m_TilingMode;         // tiling mode (none/user/auto)
   unsigned int                       m_Margin;             // stability margin related to m_NumberOfFirstIterations
   std::vector<ProcessingTile>        m_Tiles;              // list of tiles
-  std::vector<std::string>           m_TemporaryFilesList; // list of temporary files
   typename LabelImageType::Pointer   m_LabelImage;         // output label image
 };
 } // end of namespace lsgrm
diff --git a/include/lsgrmController.txx b/include/lsgrmController.txx
index 052911bf3be7065d4c986afb8dea591b5967ce4a..ec776b6c8eaa63b5fabae45925891e8c1b68f957 100644
--- a/include/lsgrmController.txx
+++ b/include/lsgrmController.txx
@@ -14,7 +14,7 @@ Controller<TSegmenter>::Controller()
   m_TileWidth = 0;
   m_NbTilesX = 0;
   m_NbTilesY = 0;
-  m_CleanTemporaryDirectory = true;
+  m_CleanTemporaryFiles = true;
   m_Threshold = 75;
   m_Memory = 0;
 }
@@ -53,8 +53,8 @@ void Controller<TSegmenter>::RunSegmentation()
         "\n\tTiling layout: " << m_NbTilesX << " x " << m_NbTilesY << std::endl;
 
     // Compute the splitting scheme
-    SplitOTBImage<ImageType>(m_InputImage, m_TileWidth, m_TileHeight, m_Margin,
-        m_NbTilesX, m_NbTilesY, m_Tiles);
+    m_Tiles = SplitOTBImage<ImageType>(m_InputImage, m_TileWidth, m_TileHeight, m_Margin,
+        m_NbTilesX, m_NbTilesY, m_TemporaryFilesPrefix);
 
     // Boolean indicating if there are remaining fusions
     bool isFusion = false;
@@ -72,9 +72,7 @@ void Controller<TSegmenter>::RunSegmentation()
         m_NbTilesY,
         m_TileWidth,
         m_TileHeight,
-        m_TemporaryDirectory,
         isFusion);
-    //    long long unsigned int accumulatedMemory = 19373051714;
 
     // Update the given number of iterations
     numberOfIterationsRemaining -= m_NumberOfFirstIterations;
@@ -96,7 +94,6 @@ void Controller<TSegmenter>::RunSegmentation()
           m_Threshold,
           numberOfIterationsForPartialSegmentations,
           m_Tiles,
-          m_TemporaryDirectory,
           m_NbTilesX,
           m_NbTilesY,
           m_InputImage->GetLargestPossibleRegion().GetSize()[0],
@@ -127,7 +124,6 @@ void Controller<TSegmenter>::RunSegmentation()
           m_SpecificParameters,
           m_Threshold,
           m_Tiles,
-          m_TemporaryDirectory,
           m_NbTilesX,
           m_NbTilesY,
           m_InputImage->GetLargestPossibleRegion().GetSize()[0],
@@ -176,7 +172,7 @@ unsigned int Controller<TSegmenter>::GetNodeMemory()
   lsrm::GraphOperations<TSegmenter>::InitNodes(onePixelImage,segmenter,FOUR);
 
   unsigned int memory = segmenter.GetGraphMemory() / (n*n);
-  itkWarningMacro(<<"Size of a node is " << memory);
+  itkDebugMacro(<<"Size of a node is " << memory);
   return memory;
 }
 
@@ -198,7 +194,8 @@ long unsigned int Controller<TSegmenter>::GetMaximumNumberOfNodesInMemory()
 }
 
 template<class TSegmenter>
-void Controller<TSegmenter>::ComputeMaximumStabilityMargin(unsigned int width,
+void
+Controller<TSegmenter>::ComputeMaximumStabilityMargin(unsigned int width,
     unsigned int height, unsigned int &niter, unsigned int &margin)
     {
   itkDebugMacro(<< "Computing maximum stability margin");
@@ -331,7 +328,7 @@ void Controller<TSegmenter>::GetAutomaticConfiguration()
   long long unsigned int memoryUsed = GetNodeMemory();
   memoryUsed *= static_cast<long long unsigned int>(m_TileHeight + 2*m_Margin);
   memoryUsed *= static_cast<long long unsigned int>(m_TileWidth + 2*m_Margin);
-  itkWarningMacro(<< "An amount of " << memoryUsed/(1024.0*1024.0) << " Mbytes of RAM will be used for regular tiles of size "
+  itkDebugMacro(<< "An amount of " << memoryUsed/(1024.0*1024.0) << " Mbytes of RAM will be used for regular tiles of size "
       << (m_TileWidth + 2*m_Margin) << "x" << (m_TileHeight + 2*m_Margin) );
 
 }
diff --git a/include/lsgrmGraphOperations.h b/include/lsgrmGraphOperations.h
index ae7c6ad78f061e305bba66db88197c8d1ae4f5ef..b2e52e9077c9f773f321f57ae750295f741e89d9 100644
--- a/include/lsgrmGraphOperations.h
+++ b/include/lsgrmGraphOperations.h
@@ -16,6 +16,12 @@ struct ProcessingTile
   long int tileNeighbors[8]; // tile Neighbors at (top, top right, right, bottom right, bottom, bottom left, left, top left)
   long int margin[4]; // Is there a margin at top, left, bottom or right
   otb::VectorImage<double>::RegionType region; // The image region
+
+  // Temporary files
+  std::string nodeFileName;
+  std::string edgeFileName;
+  std::string nodeMarginFileName;
+  std::string edgeMarginFileName;
 };
 
 // Read an image region
@@ -30,7 +36,6 @@ MergeAllGraphsAndAchieveSegmentation(
     const typename TSegmenter::ParameterType& params,
     const float& threshold,
     std::vector<ProcessingTile>& tiles,
-    const std::string& tmpDir,
     const unsigned int nbTilesX,
     const unsigned int nbTilesY,
     const unsigned int imageWidth,
@@ -50,7 +55,6 @@ long long unsigned int RunFirstPartialSegmentation(
     const unsigned int nbTilesY,
     const unsigned int tileWidth,
     const unsigned int tileHeight,
-    const std::string& tmpDir,
     bool& isFusion);
 
 template<class TSegmenter>
@@ -59,7 +63,6 @@ long long unsigned int RunPartialSegmentation(
     const float& threshold,
     const unsigned int niter,
     std::vector<ProcessingTile>& tiles,
-    const std::string& tmpDir,
     const unsigned int nbTilesX,
     const unsigned int nbTilesY,
     const unsigned int imageWidth,
@@ -101,9 +104,13 @@ void BuildBorderPixelMap(typename TSegmenter::GraphType& graph,
     std::vector<typename TSegmenter::NodePointerType> >& borderPixelMap,
     const unsigned int imageWidth);
 
+template<class TSegmenter>
+void InsertNodesFromTile(typename TSegmenter::GraphType& graph,
+    ProcessingTile& tile, bool margin = true);
+
 template<class TSegmenter>
 void AddStabilityMargin(typename TSegmenter::GraphType& graph,
-    const std::string& tmpDir,
+    std::vector<ProcessingTile>& tiles,
     const unsigned int row,
     const unsigned int col,
     const unsigned int nbTilesX,
@@ -134,18 +141,19 @@ void DetectBorderNodes(typename TSegmenter::GraphType& graph,
     const unsigned int imageHeight);
 
 template<class TSegmenter>
-void ReadGraph(typename TSegmenter::GraphType& graph,
+void ReadGraph(TSegmenter& segmenter,
     const std::string& nodesPath,
     const std::string& edgesPath);
 
 template<class TSegmenter>
-void WriteGraph(typename TSegmenter::GraphType& graph,
-    const std::string& tmpDir,
-    const unsigned int row,
-    const unsigned int col);
+void ReadGraph(typename TSegmenter::GraphType& graph,
+    const std::string& nodesPath,
+    const std::string& edgesPath);
 
 template<class TSegmenter>
-long long unsigned int GetGraphMemory(TSegmenter segmenter);
+void WriteGraph(typename TSegmenter::GraphType& graph,
+    const std::string& nodesFile,
+    const std::string& edgesFile);
 
 template<class TSegmenter>
 void RemoveUnstableSegments(typename TSegmenter::GraphType& graph,
diff --git a/include/lsgrmGraphOperations.txx b/include/lsgrmGraphOperations.txx
index d37e5aa16fa415de38738a469b717bf6a7f10606..c7edae657b9ffc19ff49f4bd4a9e9dd736b7fce6 100644
--- a/include/lsgrmGraphOperations.txx
+++ b/include/lsgrmGraphOperations.txx
@@ -27,7 +27,6 @@ MergeAllGraphsAndAchieveSegmentation(
     const typename TSegmenter::ParameterType& params,
     const float& threshold,
     std::vector<ProcessingTile>& tiles,
-    const std::string& tmpDir,
     const unsigned int nbTilesX,
     const unsigned int nbTilesY,
     const unsigned int imageWidth,
@@ -36,16 +35,16 @@ MergeAllGraphsAndAchieveSegmentation(
     unsigned int numberOfIterations)
 {
 
-  // TODO parallelize this ...
+  std::cout << "--- Graph aggregation...\n" << std::endl;
+
+  // TODO parallelize this ?
 #ifdef OTB_USE_MPI
   if (otb::MPIConfig::Instance()->GetMyRank() != 0)
     return;
 #endif
 
   TSegmenter segmenter;
-  std::string nodesPath, edgesPath;
 
-  std::cout << "--- Graph aggregation...\n" << std::endl;
 
   std::cout << "Reading graphs" << std::endl;
 
@@ -55,16 +54,7 @@ MergeAllGraphsAndAchieveSegmentation(
       {
       std::cout << "\tImporting graph of tile " << (row*nbTilesX + col) << " / " << (nbTilesX*nbTilesY) << std::endl;
 
-      typename TSegmenter::GraphType graph;
-
-      // Load the graph
-      nodesPath = tmpDir + "tile_nodes_" + std::to_string(row) + "_" + std::to_string(col) + ".bin";
-      edgesPath = tmpDir + "tile_edges_" + std::to_string(row) + "_" + std::to_string(col) + ".bin";
-      ReadGraph<TSegmenter>(graph, nodesPath, edgesPath);
-
-      segmenter.m_Graph.m_Nodes.insert(segmenter.m_Graph.m_Nodes.end(),
-          graph.m_Nodes.begin(),
-          graph.m_Nodes.end());
+      InsertNodesFromTile<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], false);
       }
     }
 
@@ -95,7 +85,6 @@ MergeAllGraphsAndAchieveSegmentation(
       }
     }
 
-
   std::cout << "Achieve segmentation process" ;
 
   // Segmentation of the graph
@@ -121,7 +110,6 @@ long long unsigned int RunPartialSegmentation(const typename TSegmenter::Paramet
     const float& threshold,
     const unsigned int niter,
     std::vector<ProcessingTile>& tiles,
-    const std::string& tmpDir,
     const unsigned int nbTilesX,
     const unsigned int nbTilesY,
     const unsigned int imageWidth,
@@ -130,7 +118,6 @@ long long unsigned int RunPartialSegmentation(const typename TSegmenter::Paramet
     bool& isFusion)
 {
   long long unsigned int accumulatedMemory = 0;
-  std::string nodesPath, edgesPath;
   isFusion = false;
 
   const unsigned int numberOfNeighborLayers = static_cast<unsigned int>(pow(2, niter + 1) - 2);
@@ -143,28 +130,27 @@ long long unsigned int RunPartialSegmentation(const typename TSegmenter::Paramet
       {
       if (MyTurn(row*nbTilesX + col))
         {
+        // Get the current tile
+        ProcessingTile currentTile = tiles[row*nbTilesX + col];
+
         TSegmenter segmenter;
         std::cout << "Processing tile " << row << ", " << col << std::endl;
         std::cout << "\tLoad graph..." << std::endl;
 
         // Load the graph
-        nodesPath = tmpDir + "tile_nodes_" + std::to_string(row) + "_" + std::to_string(col) + ".bin";
-        edgesPath = tmpDir + "tile_edges_" + std::to_string(row) + "_" + std::to_string(col) + ".bin";
-        ReadGraph<TSegmenter>(segmenter.m_Graph, nodesPath, edgesPath);
-
+        ReadGraph<TSegmenter>(segmenter.m_Graph, currentTile.nodeFileName, currentTile.edgeFileName);
 
         // Add stability margin to the graph
         {
           std::cout << "\tAdd stability margin..." << std::endl;
-          AddStabilityMargin<TSegmenter>(segmenter.m_Graph, tmpDir,
+          AddStabilityMargin<TSegmenter>(segmenter.m_Graph, tiles,
               row, col, nbTilesX, nbTilesY);
 
-
           std::unordered_map<long unsigned int,
           std::vector<typename TSegmenter::NodePointerType> > borderPixelMap;
 
           std::cout << "\tBuild border pixel map..." << std::endl;
-          BuildBorderPixelMap<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], row, col,
+          BuildBorderPixelMap<TSegmenter>(segmenter.m_Graph, currentTile, row, col,
               nbTilesX, nbTilesY, borderPixelMap, imageWidth);
 
           std::cout << "\tRemove duplicated nodes..." << std::endl;
@@ -176,7 +162,7 @@ long long unsigned int RunPartialSegmentation(const typename TSegmenter::Paramet
               imageHeight);
 
           std::cout << "\tRemove useless.." << std::endl;
-          RemoveUselessNodes<TSegmenter>(tiles[row*nbTilesX + col], segmenter.m_Graph,
+          RemoveUselessNodes<TSegmenter>(currentTile, segmenter.m_Graph,
               row, col, nbTilesX, nbTilesY, imageWidth, numberOfNeighborLayers);
 
         }
@@ -198,15 +184,15 @@ long long unsigned int RunPartialSegmentation(const typename TSegmenter::Paramet
 
         // Remove unstable segments
         std::cout << "\tRemove unstable segments..." << std::endl;
-        RemoveUnstableSegments<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], imageWidth);
+        RemoveUnstableSegments<TSegmenter>(segmenter.m_Graph, currentTile, imageWidth);
 
         // Retrieve the amount of memory to store this graph
         std::cout << "\tGet graph memory..." << std::endl;
-        accumulatedMemory += GetGraphMemory<TSegmenter>(segmenter);
+        accumulatedMemory += segmenter.GetGraphMemory();
 
-        // Write graph to temporay directory (warning specific to Baatz & Schape !!!)
+        // Write graph to temporay directory
         std::cout << "\tWrite graph..." << std::endl;
-        WriteGraph<TSegmenter>(segmenter.m_Graph, tmpDir, row, col);
+        WriteGraph<TSegmenter>(segmenter.m_Graph, currentTile.nodeFileName, currentTile.edgeFileName);
         }
       }
     }
@@ -224,32 +210,24 @@ long long unsigned int RunPartialSegmentation(const typename TSegmenter::Paramet
       {
       if (MyTurn(row*nbTilesX + col))
         {
-        //                  std::cout << "*" << std::flush;
-        typename TSegmenter::GraphType graph;
+        // Get current tile
+        ProcessingTile currentTile = tiles[row*nbTilesX + col];
 
         // Load the graph
-        nodesPath = tmpDir + "tile_nodes_" + std::to_string(row) + "_" + std::to_string(col) + ".bin";
-        edgesPath = tmpDir + "tile_edges_" + std::to_string(row) + "_" + std::to_string(col) + ".bin";
-        ReadGraph<TSegmenter>(graph, nodesPath, edgesPath);
+        typename TSegmenter::GraphType graph;
+        ReadGraph<TSegmenter>(graph, currentTile.nodeFileName, currentTile.edgeFileName);
 
         // Extract stability margin for all borders different from 0 imageWidth-1 et imageHeight -
         // and write them to the stability margin
         {
           std::unordered_map<typename TSegmenter::NodePointerType, unsigned int> borderNodeMap;
 
-          DetectBorderNodes<TSegmenter>(graph, tiles[row*nbTilesX + col],
+          DetectBorderNodes<TSegmenter>(graph, currentTile,
               borderNodeMap, imageWidth, imageHeight);
 
-
           ExtractStabilityMargin<TSegmenter>(borderNodeMap, numberOfNeighborLayers);
 
-          std::string nodesPath = tmpDir + "tile_nodes_margin_" +
-              std::to_string(row) + "_" + std::to_string(col) + ".bin";
-          std::string edgesPath = tmpDir + "tile_edges_margin_" +
-              std::to_string(row) + "_" + std::to_string(col) + ".bin";
-
-
-          WriteStabilityMargin<TSegmenter>(borderNodeMap, nodesPath, edgesPath);
+          WriteStabilityMargin<TSegmenter>(borderNodeMap, currentTile.nodeMarginFileName, currentTile.edgeMarginFileName);
         }
         std::cout << "Process finished on tile " << (row*nbTilesX + col) << std::endl;
         }
@@ -529,156 +507,79 @@ void BuildBorderPixelMap(typename TSegmenter::GraphType& graph,
     }
 }
 
+template<class TSegmenter>
+void InsertNodesFromTile(typename TSegmenter::GraphType& graph,
+    ProcessingTile& tile, bool margin = true)
+{
+  typename TSegmenter::GraphType subgraph;
+  if (margin)
+    {
+    ReadGraph<TSegmenter>(subgraph, tile.nodeMarginFileName, tile.edgeMarginFileName);
+    }
+  else
+    {
+    ReadGraph<TSegmenter>(subgraph, tile.nodeFileName, tile.edgeFileName);
+    }
+
+  graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end());
+
+}
+
 template<class TSegmenter>
 void AddStabilityMargin(typename TSegmenter::GraphType& graph,
-    const std::string& tmpDir,
+    std::vector<ProcessingTile>& tiles,
     const unsigned int row,
     const unsigned int col,
     const unsigned int nbTilesX,
     const unsigned int nbTilesY)
 {
-  std::string nodesPath;
-  std::string edgesPath;
-  unsigned int rowNeigh;
-  unsigned int colNeigh;
 
   // Margin to retrieve at top
   if(row > 0)
     {
-    colNeigh = col;
-    rowNeigh = row-1;
-
-    nodesPath = tmpDir + "tile_nodes_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    edgesPath = tmpDir + "tile_edges_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    typename TSegmenter::GraphType subgraph;
-    ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath);
-    graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end());
+    InsertNodesFromTile<TSegmenter>(graph, tiles[(row-1) * nbTilesX + col]);
     }
 
   // Margin to retrieve at right
   if(col < nbTilesX - 1)
     {
-    colNeigh = col + 1;
-    rowNeigh = row;
-
-    nodesPath = tmpDir + "tile_nodes_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    edgesPath = tmpDir + "tile_edges_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    typename TSegmenter::GraphType subgraph;
-    ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath);
-
-    graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end());
-
+    InsertNodesFromTile<TSegmenter>(graph, tiles[row * nbTilesX + (col+1)]);
     }
 
   // Margin to retrieve at bottom
   if(row < nbTilesY - 1)
     {
-    colNeigh = col;
-    rowNeigh = row + 1;
-
-    nodesPath = tmpDir + "tile_nodes_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    edgesPath = tmpDir + "tile_edges_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    typename TSegmenter::GraphType subgraph;
-    ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath);
-    graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end());
-
+    InsertNodesFromTile<TSegmenter>(graph, tiles[(row+1) * nbTilesX + col]);
     }
 
   // Margin to retrieve at left
   if(col > 0)
     {
-    colNeigh = col-1;
-    rowNeigh = row;
-
-    nodesPath = tmpDir + "tile_nodes_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    edgesPath = tmpDir + "tile_edges_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    typename TSegmenter::GraphType subgraph;
-    ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath);
-    graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end());
+    InsertNodesFromTile<TSegmenter>(graph, tiles[row * nbTilesX + (col-1)]);
     }
 
   // Margin to retrieve at top right
   if(row > 0 && col < nbTilesX - 1)
     {
-    colNeigh = col+1;
-    rowNeigh = row-1;
-
-    nodesPath = tmpDir + "tile_nodes_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    edgesPath = tmpDir + "tile_edges_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    typename TSegmenter::GraphType subgraph;
-    ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath);
-    graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end());
+    InsertNodesFromTile<TSegmenter>(graph, tiles[(row-1) * nbTilesX + (col+1)]);
     }
 
   // Margin to retrieve at bottom right
   if(row < nbTilesY - 1 && col < nbTilesX - 1)
     {
-    colNeigh = col+1;
-    rowNeigh = row+1;
-
-    nodesPath = tmpDir + "tile_nodes_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    edgesPath = tmpDir + "tile_edges_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    typename TSegmenter::GraphType subgraph;
-    ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath);
-    graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end());
+    InsertNodesFromTile<TSegmenter>(graph, tiles[ (row+1) * nbTilesX + (col+1)]);
     }
 
   // Margin to retrieve at bottom left
   if(row < nbTilesY - 1 && col > 0)
     {
-    colNeigh = col-1;
-    rowNeigh = row+1;
-
-    nodesPath = tmpDir + "tile_nodes_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    edgesPath = tmpDir + "tile_edges_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    typename TSegmenter::GraphType subgraph;
-    ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath);
-    graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end());
+    InsertNodesFromTile<TSegmenter>(graph, tiles[ (row+1) * nbTilesX + (col-1)]);
     }
 
   // Margin to retrieve at top left
   if(row > 0 && col > 0)
     {
-    colNeigh = col-1;
-    rowNeigh = row-1;
-
-    nodesPath = tmpDir + "tile_nodes_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    edgesPath = tmpDir + "tile_edges_margin_" +
-        std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin";
-
-    typename TSegmenter::GraphType subgraph;
-    ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath);
-    graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end());
+    InsertNodesFromTile<TSegmenter>(graph, tiles[ (row-1) * nbTilesX + (col-1)]);
     }
 }
 
@@ -694,7 +595,6 @@ long long unsigned int RunFirstPartialSegmentation(
     const unsigned int nbTilesY,
     const unsigned int tileWidth,
     const unsigned int tileHeight,
-    const std::string& tmpDir,
     bool& isFusion)
 {
 
@@ -717,6 +617,7 @@ long long unsigned int RunFirstPartialSegmentation(
         {
         // Reading images
         ProcessingTile currentTile = tiles[row*nbTilesX + col];
+
         std::cout << "Processing tile " <<  (row*nbTilesX + col) << " / " << (nbTilesX*nbTilesY) <<
             " (" << col << ", " << row << ")" <<
             " start: [" << currentTile.region.GetIndex()[0] << ", " << currentTile.region.GetIndex()[1] <<
@@ -740,7 +641,7 @@ long long unsigned int RunFirstPartialSegmentation(
         // Rescale the graph to be in the reference of the image
         std::cout << "\tRescaling graph..." << std::endl;
         RescaleGraph<TSegmenter>(segmenter.m_Graph,
-            tiles[row*nbTilesX + col],
+            currentTile,
             row,
             col,
             tileWidth,
@@ -749,15 +650,15 @@ long long unsigned int RunFirstPartialSegmentation(
 
         // Remove unstable segments
         std::cout << "\tRemoving unstable segments..." << std::endl;
-        RemoveUnstableSegments<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], imageWidth);
+        RemoveUnstableSegments<TSegmenter>(segmenter.m_Graph, currentTile, imageWidth);
 
         // Retrieve the amount of memory to store this graph
         std::cout << "\tRetrieving graph memory..." << std::endl;
-        accumulatedMemory += GetGraphMemory<TSegmenter>(segmenter);
+        accumulatedMemory += segmenter.GetGraphMemory();
 
-        // Write graph to temporay directory (warning specific to Baatz & Schape !!!)
-        std::cout << "\tWriting graph..." << std::endl;
-        WriteGraph<TSegmenter>(segmenter.m_Graph, tmpDir, row, col);
+        // Write graph to temporay directory
+        std::cout << "\tWriting graph..." << currentTile.nodeFileName << " et " <<  currentTile.edgeFileName << std::endl;
+        WriteGraph<TSegmenter>(segmenter.m_Graph, currentTile.nodeFileName, currentTile.edgeFileName);
 
         // Extract stability margin for all borders different from 0 imageWidth-1 et imageHeight -1
         // and write them to the stability margin
@@ -765,19 +666,12 @@ long long unsigned int RunFirstPartialSegmentation(
         {
           std::unordered_map<typename TSegmenter::NodePointerType, unsigned int> borderNodeMap;
 
-          DetectBorderNodes<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col],
+          DetectBorderNodes<TSegmenter>(segmenter.m_Graph, currentTile,
               borderNodeMap, imageWidth, imageHeight);
 
-
           ExtractStabilityMargin<TSegmenter>(borderNodeMap, numberOfNeighborLayers);
 
-          std::string nodesPath = tmpDir + "tile_nodes_margin_" +
-              std::to_string(row) + "_" + std::to_string(col) + ".bin";
-          std::string edgesPath = tmpDir + "tile_edges_margin_" +
-              std::to_string(row) + "_" + std::to_string(col) + ".bin";
-
-
-          WriteStabilityMargin<TSegmenter>(borderNodeMap, nodesPath, edgesPath);
+          WriteStabilityMargin<TSegmenter>(borderNodeMap, currentTile.nodeMarginFileName, currentTile.edgeMarginFileName);
         }
         }
       } // for each col
@@ -889,96 +783,34 @@ void DetectBorderNodes(typename TSegmenter::GraphType& graph,
     }
 }
 
-// Specific to Baatz & Schape (sorry it has to be fast)
+
+// Generic
 template<class TSegmenter>
-void ReadGraph(typename TSegmenter::GraphType& graph,
+void ReadGraph(TSegmenter& segmenter,
     const std::string& nodesPath,
     const std::string& edgesPath)
 {
   FILE * nodeStream = fopen(nodesPath.c_str(), "r");
   assert(nodeStream != NULL);
-  std::unordered_map<long unsigned int, typename TSegmenter::NodePointerType> nodeMap;
-
-  // Read the size of the graph
-  {
-  std::size_t graphSize;
-  fread(&graphSize, sizeof(graphSize), 1, nodeStream);
-  graph.m_Nodes.reserve(graphSize);
-
-  // Creation of the nodes
-  for(std::size_t i = 0; i < graphSize; i++)
-    {
-    typename TSegmenter::NodePointerType node(new typename TSegmenter::NodeType());
-
-    node->m_Valid = true;
-    node->m_Expired = false;
-    node->m_IsMerged = true; // force to compute costs for the first iteration
-
-    fread(&(node->m_Id), sizeof(node->m_Id), 1, nodeStream);
-    fread(&(node->m_Perimeter), sizeof(node->m_Perimeter), 1, nodeStream);
-    fread(&(node->m_Area), sizeof(node->m_Area), 1, nodeStream);
-    fread(&(node->m_Bbox.m_UX), sizeof(node->m_Bbox.m_UX), 1, nodeStream);
-    fread(&(node->m_Bbox.m_UY), sizeof(node->m_Bbox.m_UY), 1, nodeStream);
-    fread(&(node->m_Bbox.m_W), sizeof(node->m_Bbox.m_W), 1, nodeStream);
-    fread(&(node->m_Bbox.m_H), sizeof(node->m_Bbox.m_H), 1, nodeStream);
-
-    std::size_t bands;
-    fread(&(bands), sizeof(bands), 1, nodeStream);
-    node->m_Means.assign(bands, 0);
-    node->m_SquareMeans.assign(bands, 0);
-    node->m_SpectralSum.assign(bands, 0);
-    node->m_Std.assign(bands, 0);
-
-    for(unsigned int b = 0; b < bands; b++)
-      {
-      fread(&(node->m_Means[b]), sizeof(node->m_Means[b]), 1, nodeStream);
-      fread(&(node->m_SquareMeans[b]), sizeof(node->m_SquareMeans[b]), 1, nodeStream);
-      fread(&(node->m_SpectralSum[b]), sizeof(node->m_SpectralSum[b]), 1, nodeStream);
-      fread(&(node->m_Std[b]), sizeof(node->m_Std[b]), 1, nodeStream);
-      }
-
-    {
-    std::size_t contourSize;
-    fread(&(contourSize), sizeof(contourSize), 1, nodeStream);
-    short moves[contourSize];
-    fread(&moves, sizeof(short), contourSize, nodeStream);
-    for(unsigned int b = 0; b < contourSize; b++)
-      {
-      node->m_Contour.push_back(moves[b]);
-      }
-    }
-    nodeMap[node->m_Id] = node;
-    graph.m_Nodes.push_back(node);
-    }
-  }
-  fclose(nodeStream);
-
-  // Build edges with nodeMap
   FILE * edgeStream = fopen(edgesPath.c_str(), "r");
   assert(edgeStream != NULL);
 
-  for(auto& node: graph.m_Nodes)
-    {
-    long unsigned int nodeId;
-    fread(&(nodeId), sizeof(nodeId), 1, edgeStream);
-    assert(nodeId == node->m_Id);
-
-    std::size_t edgeSize;
-    fread(&(edgeSize), sizeof(edgeSize), 1, edgeStream);
-    node->m_Edges.reserve(edgeSize);
-    for(unsigned int b = 0; b < edgeSize; b++)
-      {
-      long unsigned int targetId;
-      unsigned int boundary;
-      fread(&(targetId), sizeof(targetId), 1, edgeStream);
-      fread(&(boundary), sizeof(boundary), 1, edgeStream);
-      node->m_Edges.push_back(typename TSegmenter::EdgeType(nodeMap[targetId], 0, boundary));
-      }
-    }
+  segmenter.ReadGraph(nodeStream, edgeStream);
 
+  fclose(nodeStream);
   fclose(edgeStream);
 }
 
+template<class TSegmenter>
+void ReadGraph(typename TSegmenter::GraphType& graph,
+    const std::string& nodesPath,
+    const std::string& edgesPath)
+{
+  TSegmenter segmenter;
+  ReadGraph<TSegmenter>(segmenter, nodesPath, edgesPath);
+  graph = segmenter.m_Graph;
+}
+
 // Write stability margin
 template<class TSegmenter>
 void WriteStabilityMargin(std::unordered_map<
@@ -992,52 +824,19 @@ void WriteStabilityMargin(std::unordered_map<
   FILE * edgeStream = fopen(edgesPath.c_str(), "wb");
   assert(edgeStream != NULL);
 
-  // Write size of the graph
-  {
-    // Write number of nodes
-    std::size_t size = stabilityMargin.size();
-    fwrite(&size, sizeof(size), 1, nodeStream);
-  }
+  // Write number of nodes
+  std::size_t size = stabilityMargin.size();
+  fwrite(&size, sizeof(size), 1, nodeStream);
 
+  TSegmenter seg;
   for(auto& kv : stabilityMargin)
     {
     auto node = kv.first;
-
-    fwrite(&(node->m_Id), sizeof(node->m_Id), 1, nodeStream);
-    fwrite(&(node->m_Perimeter), sizeof(node->m_Perimeter), 1, nodeStream);
-    fwrite(&(node->m_Area), sizeof(node->m_Area), 1, nodeStream);
-    fwrite(&(node->m_Bbox.m_UX), sizeof(node->m_Bbox.m_UX), 1, nodeStream);
-    fwrite(&(node->m_Bbox.m_UY), sizeof(node->m_Bbox.m_UY), 1, nodeStream);
-    fwrite(&(node->m_Bbox.m_W), sizeof(node->m_Bbox.m_W), 1, nodeStream);
-    fwrite(&(node->m_Bbox.m_H), sizeof(node->m_Bbox.m_H), 1, nodeStream);
-
-    std::size_t bands = node->m_Means.size();
-    fwrite(&(bands), sizeof(bands), 1, nodeStream);
-
-    for(unsigned int b = 0; b < node->m_Means.size(); b++)
-      {
-      fwrite(&(node->m_Means[b]), sizeof(node->m_Means[b]), 1, nodeStream);
-      fwrite(&(node->m_SquareMeans[b]), sizeof(node->m_SquareMeans[b]), 1, nodeStream);
-      fwrite(&(node->m_SpectralSum[b]), sizeof(node->m_SpectralSum[b]), 1, nodeStream);
-      fwrite(&(node->m_Std[b]), sizeof(node->m_Std[b]), 1, nodeStream);
-      }
-
-    {
-    std::size_t contourSize = node->m_Contour.size();
-    fwrite(&(contourSize), sizeof(contourSize), 1, nodeStream);
-    short moves[contourSize];
-    for(unsigned int b = 0; b < contourSize; b++)
-      {
-      moves[b] = node->m_Contour[b];
-      }
-    fwrite(moves, sizeof(short), contourSize, nodeStream);
-    }
+    seg.WriteNode(node, nodeStream);
 
     // Write only edges pointing to nodes which are in the stability margin.
-
     fwrite(&(node->m_Id), sizeof(node->m_Id), 1, edgeStream);
     std::size_t edgeSize = node->m_Edges.size();
-
     for(auto& edg : node->m_Edges)
       {
       if(stabilityMargin.find(edg.GetRegion()) == stabilityMargin.end())
@@ -1048,8 +847,7 @@ void WriteStabilityMargin(std::unordered_map<
       {
       if(stabilityMargin.find(edg.GetRegion()) != stabilityMargin.end())
         {
-        fwrite(&(edg.GetRegion()->m_Id), sizeof(edg.GetRegion()->m_Id), 1, edgeStream);
-        fwrite(&(edg.m_Boundary), sizeof(edg.m_Boundary), 1, edgeStream);
+        seg.WriteEdge(edg, edgeStream);
         }
       }
     }
@@ -1058,65 +856,26 @@ void WriteStabilityMargin(std::unordered_map<
   fclose(edgeStream);
 }
 
-// Specific to Baatz & Schape (sorry it has to be fast)
+// Write the graph
 template<class TSegmenter>
 void WriteGraph(typename TSegmenter::GraphType& graph,
-    const std::string& tmpDir,
-    const unsigned int row,
-    const unsigned int col)
+    const std::string& nodeFile,
+    const std::string& edgeFile)
 {
-  // One file for the nodes
-  std::string nodeFile = tmpDir + "tile_nodes_" +
-      std::to_string(row) + "_" + std::to_string(col) + ".bin";
-  // One file for the edges
-  std::string edgeFile = tmpDir + "tile_edges_" +
-      std::to_string(row) + "_" + std::to_string(col) + ".bin";
 
   FILE * nodeStream = fopen(nodeFile.c_str(), "wb");
   assert(nodeStream != NULL);
   FILE * edgeStream = fopen(edgeFile.c_str(), "wb");
   assert(edgeStream != NULL);
 
-  // Write size of the graph
-  {
-    // Write number of nodes
-    std::size_t size = graph.m_Nodes.size();
-    fwrite(&size, sizeof(size), 1, nodeStream);
-  }
-
+  // Write number of nodes
+  std::size_t size = graph.m_Nodes.size();
+  fwrite(&size, sizeof(size), 1, nodeStream);
 
+  TSegmenter seg;
   for(auto& node : graph.m_Nodes)
     {
-
-    fwrite(&(node->m_Id), sizeof(node->m_Id), 1, nodeStream);
-    fwrite(&(node->m_Perimeter), sizeof(node->m_Perimeter), 1, nodeStream);
-    fwrite(&(node->m_Area), sizeof(node->m_Area), 1, nodeStream);
-    fwrite(&(node->m_Bbox.m_UX), sizeof(node->m_Bbox.m_UX), 1, nodeStream);
-    fwrite(&(node->m_Bbox.m_UY), sizeof(node->m_Bbox.m_UY), 1, nodeStream);
-    fwrite(&(node->m_Bbox.m_W), sizeof(node->m_Bbox.m_W), 1, nodeStream);
-    fwrite(&(node->m_Bbox.m_H), sizeof(node->m_Bbox.m_H), 1, nodeStream);
-
-    std::size_t bands = node->m_Means.size();
-    fwrite(&(bands), sizeof(bands), 1, nodeStream);
-
-    for(unsigned int b = 0; b < node->m_Means.size(); b++)
-      {
-      fwrite(&(node->m_Means[b]), sizeof(node->m_Means[b]), 1, nodeStream);
-      fwrite(&(node->m_SquareMeans[b]), sizeof(node->m_SquareMeans[b]), 1, nodeStream);
-      fwrite(&(node->m_SpectralSum[b]), sizeof(node->m_SpectralSum[b]), 1, nodeStream);
-      fwrite(&(node->m_Std[b]), sizeof(node->m_Std[b]), 1, nodeStream);
-      }
-
-    {
-    std::size_t contourSize = node->m_Contour.size();
-    fwrite(&(contourSize), sizeof(contourSize), 1, nodeStream);
-    short moves[contourSize];
-    for(unsigned int b = 0; b < contourSize; b++)
-      {
-      moves[b] = node->m_Contour[b];
-      }
-    fwrite(moves, sizeof(short), contourSize, nodeStream);
-    }
+    seg.WriteNode(node, nodeStream);
 
     // Write edges
     fwrite(&(node->m_Id), sizeof(node->m_Id), 1, edgeStream);
@@ -1124,8 +883,7 @@ void WriteGraph(typename TSegmenter::GraphType& graph,
     fwrite(&(edgeSize), sizeof(edgeSize), 1, edgeStream);
     for(auto& edg : node->m_Edges)
       {
-      fwrite(&(edg.GetRegion()->m_Id), sizeof(edg.GetRegion()->m_Id), 1, edgeStream);
-      fwrite(&(edg.m_Boundary), sizeof(edg.m_Boundary), 1, edgeStream);
+      seg.WriteEdge(edg, edgeStream);
       }
     }
 
@@ -1133,29 +891,6 @@ void WriteGraph(typename TSegmenter::GraphType& graph,
   fclose(edgeStream);
 }
 
-template<class TSegmenter>
-long long unsigned int GetGraphMemory(TSegmenter segmenter)
-{
-//  TSegmenter::GraphType graph = segmenter.graph;
-//  long long unsigned int memory = 0;
-//  long unsigned int numberOfMoves = 0;
-//
-//  // Amount of memory needed to store the nodes
-//  memory += graph.m_Nodes.size() * (sizeof(*graph.m_Nodes.begin()) + sizeof(graph.m_Nodes.begin()) + 4 * sizeof(float));
-//
-//  for(auto& node : graph.m_Nodes)
-//    {
-//    memory += node->m_Edges.size() * (sizeof(*node->m_Edges.begin()) + sizeof(node->m_Edges.begin()));
-//    numberOfMoves += node->m_Contour.size();
-//    }
-//
-//  memory += std::ceil(numberOfMoves / 4);
-//
-//  return memory;
-
-  return segmenter.GetGraphMemory();
-}
-
 template<class TSegmenter>
 void RemoveUnstableSegments(typename TSegmenter::GraphType& graph,
     ProcessingTile& tile,
@@ -1236,29 +971,13 @@ void RescaleGraph(typename TSegmenter::GraphType& graph,
   unsigned int rowNodeTile, colNodeTile;
   unsigned int rowNodeImg, colNodeImg;
 
-//  unsigned int currTileWidth = tile.columns[1] - tile.columns[0] + 1;
-//  currTileWidth += tile.margin[1];
-//  currTileWidth += tile.margin[3];
-//  unsigned int diffHeightMargin = tile.margin[0];
-//  unsigned int diffWidthMargin = tile.margin[3];
-
   for(auto& node : graph.m_Nodes)
     {
-
-//    // Row of the start pixel of the node
-//    rowNodeTile = node->m_Id / currTileWidth;
-//    // Col of the start pixel of the node
-//    colNodeTile = node->m_Id % currTileWidth;
-//
-//    // Row of the start pixel of the node in the image
-//    rowNodeImg = rowTile * tileHeight + rowNodeTile - diffHeightMargin;
-//    // Col of the start pixel of the node in the image
-//    colNodeImg = colTile * tileWidth + colNodeTile - diffWidthMargin;
-//
-//    node->m_Id = rowNodeImg * imageWidth + colNodeImg;
-
+    // Start pixel index of the node (in the tile)
     rowNodeTile = node->m_Id / tile.region.GetSize()[0];
     colNodeTile = node->m_Id % tile.region.GetSize()[0];
+
+    // Start pixel index of the node (in the image)
     rowNodeImg = rowTile * tileHeight + rowNodeTile - tile.margin[0];
     colNodeImg = colTile * tileWidth + colNodeTile - tile.margin[3];
     node->m_Id = rowNodeImg * imageWidth + colNodeImg;