diff --git a/tools/ggDeco/ggDeco.ml b/tools/ggDeco/ggDeco.ml
index 8758f29b6e16b7c187627e37fbc427c5c878e745..7803c51822e7a94e7d841be449da12da33881782 100644
--- a/tools/ggDeco/ggDeco.ml
+++ b/tools/ggDeco/ggDeco.ml
@@ -55,5 +55,5 @@ let () = (
     let args = parse Sys.argv in 
     let g = read args.dot_file in
       let new_g = deco g args.files_spec in 
-      make_dot new_g args.output
+      make_dot new_g args.output attr
 )
diff --git a/tools/graphgen/graphGen.ml b/tools/graphgen/graphGen.ml
index 5eb5240e4393b04756a65b8b981a81791103c86a..ae66f1543baa3da7fef0abc16578874df4080761 100644
--- a/tools/graphgen/graphGen.ml
+++ b/tools/graphgen/graphGen.ml
@@ -1,10 +1,18 @@
-open Sasacore.Topology
+open Sasacore
+open Topology
+open GraphProp
 
 open ClassicGraph
 open RandomGraph
 open GraphGen_arg
 open UdgUtils
 
+exception Incorrect_attribute
+
+let min_max = ref None 
+let connected_cyclic = ref None  
+let height = ref None
+
 let generate_du_dur graph plan_udg t : unit =
   
   if (t.dotUDG <> "") then (
@@ -15,6 +23,35 @@ let generate_du_dur graph plan_udg t : unit =
   );
   ()
 
+let compute_attr : (Topology.t -> string list -> (string*string) list) =
+  fun g -> List.map (fun attr -> 
+    attr,match attr with
+    | "min_deg" -> string_of_int (match !min_max with
+                   | None -> (let x = get_degree g in min_max := Some x; fst x)
+                   | Some x -> fst x)
+    | "mean_deg" -> string_of_float (get_mean_degree g)
+    | "max_deg" -> string_of_int (match !min_max with
+                   | None -> (let x = get_degree g in min_max := Some x; snd x)
+                   | Some x -> snd x)
+    | "is_connected" -> string_of_bool (match !connected_cyclic with
+                        | None -> (let x = is_connected_and_cyclic g in connected_cyclic := Some x; fst x)
+                        | Some x -> fst x )
+    | "is_cyclic" -> string_of_bool (match !connected_cyclic with
+                     | None -> (let x = is_connected_and_cyclic g in connected_cyclic := Some x; snd x)
+                     | Some x -> snd x )
+    | "is_tree" -> string_of_bool (match !connected_cyclic with
+                   | None -> (let x = is_connected_and_cyclic g in connected_cyclic := Some x; (fst x) && (snd x))
+                   | Some x -> (fst x) && (snd x) )
+    | "links_number" -> string_of_int (get_nb_link g false)
+    | "diameter" -> string_of_int (get_diameter g)
+    | s -> string_of_int (let s = String.split_on_char ' ' s in
+           if List.hd s = "height" && List.length s = 2 then
+             get_height g (List.hd (List.tl s))
+           else raise Incorrect_attribute)
+  )
+
+  
+
 let () = (
   let t = parse Sys.argv in
 
@@ -54,7 +91,7 @@ let () = (
     | _ -> (Printf.fprintf stderr "Unexpected outcome. Command line : %s\n" 
       (String.concat " " (Array.to_list Sys.argv)); assert false)
   ) in
-    make_dot g t.outputFile;
+    make_dot g t.outputFile (compute_attr g t.attr);
   if (t.outputFile <> "" && not t.silent) 
     then Printf.printf "Done.\nOutput file : '%s'\n" t.outputFile
 )
diff --git a/tools/graphgen/graphGen_arg.ml b/tools/graphgen/graphGen_arg.ml
index e55b17c6ace511f30e6d991b838c56f651bbc8dd..215579a4ebc7065bfcad706e6347668d2f7b7477 100644
--- a/tools/graphgen/graphGen_arg.ml
+++ b/tools/graphgen/graphGen_arg.ml
@@ -30,6 +30,8 @@ type t = {
   mutable ba : ba_m;
   mutable qudg : qudg_arg;
 
+  mutable attr : string list;
+
   mutable silent : bool;
 
   mutable _args : (string * Arg.spec * string) list;
@@ -77,6 +79,8 @@ let (make_args : unit -> t) =
         p = 0.5;
       };
 
+      attr = [];
+
       silent = false;
 
       _args  = [];
@@ -280,6 +284,13 @@ let (mkoptab : string array -> t -> unit) =
       [(["Remove all outputs, except the dot output if it is on stdout,";
         "and the error if one occurred.\n"],"void")];
 
+    args._man <- ("--attributes, -atr <attributes>...", [([
+        "Specify the given attributes of the graph to his DOT file.";
+        "the possible attributes are :";
+        "min_deg, mean_deg, max_deg, is_connected, is_cyclic, is_tree, links_number, 
+        diameter, height i (with i being the index of a node)"
+      ],"void")])::args._man;
+
     mkopt args ["--help";"-h"]
       (Arg.Unit (fun () -> help args ((argv.(0))^(if args.action = "void" then "" 
         else " "^args.action))))
@@ -310,7 +321,21 @@ let parse argv = (
 
    Arg.parse_argv ~current:current argv args._args (add_other args) (usage_msg false (argv.(0)^argv.(1)));
     current := save_current;
-    if (List.length args._others) <> 0 then unexpected (List.hd args._others);
+    args._others <- List.rev args._others;
+    let have_atr = ref false in
+    (List.iter (fun o -> 
+      if !have_atr then (
+        if (String.sub o 0 1) = "-" then 
+          unexpected o
+        else
+          args.attr <- o::args.attr
+      ) else (
+        if List.mem o ["--attributes";"-atr"] then 
+          have_atr := true
+        else
+          unexpected o
+      )
+    ) args._others);
     args
   )
   with
diff --git a/tools/graphgen/graphGen_arg.mli b/tools/graphgen/graphGen_arg.mli
index ec4612aac4e38a8267a1b93133af127c7780160b..70eda6d08b2c1ac7142cf488f2038518bc71acf3 100644
--- a/tools/graphgen/graphGen_arg.mli
+++ b/tools/graphgen/graphGen_arg.mli
@@ -28,6 +28,8 @@ type t = {
   mutable ba : ba_m;
   mutable qudg : qudg_arg;
 
+  mutable attr : string list;
+
   mutable silent : bool;
 
   mutable _args : (string * Arg.spec * string) list;
diff --git a/tools/scriptEnv.py b/tools/scriptEnv.py
index 1e435bf75b5ef3c90152f9a1f3adb41e42a9b32f..c3028dbe26a7b69300a55caabb7dd4d5ef532c58 100644
--- a/tools/scriptEnv.py
+++ b/tools/scriptEnv.py
@@ -1,4 +1,4 @@
-import subprocess, os, datetime
+import subprocess, os, datetime, math
 
 def call(command, log = None, verb = 2, options = {}):
 	"""Calls the shell command given in argument, and give its output in stdout as return value
@@ -67,7 +67,7 @@ def genGraph(graphType, outputFile, options, is_silent = False, log = None, verb
 
 	Args:
 	    graphType (str): The first argument given to 'gg', corresponding to the command in 'gg <command>'.
-	                     Use 'gg -h' in console to view the avaible commands (corresponding to avaible graphTypes).
+	                     Use 'gg -h' in console to view the available commands (corresponding to available graphTypes).
 	    outputFile (str): The output file given to 'gg' with the option '-o'. 
 	                      We strongly advice to give it a '.dot' extension
 	    graphProperties (dict): options given to 'call' function.
@@ -250,49 +250,57 @@ def column(i, matrix, names = None):
 	if names != None : i = names.index(i)
 	return [x[i] for x in matrix]
 
-class Project:
+class FileManager:
 	"""Manage files of a project, to keep traces of a test battery.
 	Inside a project directory, there will be a directory for each version 
 	(i.e. for each creation of a Project object). 
+
+	Proprieties : 
+	    path (str) : the path to the current version
 	"""
 
-	def __init__(self, projectName = "sasaProject", date = True, time = True):
+	def __init__(self, projectName = "sasaProject", version_name = "", date = True, time = True, add_index = True):
 		"""Initialize a version of the project. 
 
 		Args :
 		    projectName (str) : The name of the project, in which a new version will be created.
-		    date (bool, optional) : indicates if the version's name will contain the date 
-		    time (bool, optional) : indicates if the version's name will contain the time
-		
-		Note : if an old version has the same name as the new one, a number will be added to the new
-		       version's name.
+		    version_name (str, optional) : indicates the version's name base name
+		    date (bool, optional) : indicates if the version's name will contain the date after the base name
+		    time (bool, optional) : indicates if the version's name will contain the time after the date or base name
+		    add_index (bool, optional) : indicates if the version's name will contain an index if a version of the same 
+		                                 name already exists (to ensure not to mix an old version with the new one).
 
 		"""
 
-		self.name = projectName
-		identifyer = ""
+		self.name = projectName # the name of the project
+		version = version_name
 		now = str(datetime.datetime.now()).split()
+		if version_name == "" and date:
+			version += "_"
 		if date:
-			identifyer += now[0]
+			version += now[0]
 		if date and time:
-			identifyer += "_"
+			version += "_"
 		if time:
-			identifyer += now[1].split(".")[0]
+			version += now[1].split(".")[0]
 
 		try:
 			os.makedirs(projectName)
 		except FileExistsError:
 			pass
 		
-		if os.path.exists(projectName+"/"+identifyer) :
+		if os.path.exists(projectName+"/"+version) and add_index :
 			i = 0
-			while os.path.exists(projectName+"/"+identifyer+"_"+str(i)):i += 1
-			identifyer += "_"+str(i)
+			while os.path.exists(projectName+"/"+version+"_"+str(i)):i += 1
+			version += "_"+str(i)
 
-		os.makedirs(projectName+"/"+identifyer)
-		self.identifyer = identifyer
-		self.path = projectName+"/"+identifyer+"/"
-		self.folders = []
+		try :
+			os.makedirs(projectName+"/"+version)
+		except FileExistsError:
+			if add_index : raise
+
+		self.version = version # the name of the version
+		self.path = projectName+"/"+version+"/" # the path to the version
 
 	def createDir (self, dir):
 		"""Creates the directory dir in the current version if it doesn't exist. 
@@ -309,8 +317,8 @@ class Project:
 		except FileExistsError:
 			return False
 
-	def open(self, dir, name, ext):
-		"""Opens a new file in the directory dir of the current version.
+	def open(self, dir, name, ext, openType = 'w+', add_index = True):
+		"""Use the built-in function open() to open a file in the directory 'dir' of the current version.
 
 		The actual name of the file is 'name_i.ext', with name and ext being the arguments of the same name,
 		and i being the lower number such as no other file has the same name.
@@ -319,9 +327,15 @@ class Project:
 		    dir (str) : the name of the directory in which the file will be created. Creates it if it doesn't exists.
 		    name (str) : the name of the file, without extension. 
 		    ext (str) : the extension of the file. If it doesn't start by a point ('.'), it will be added.
+		    openType (str, optional) : the second argument given to the built-in function open(). 
+		                               Note that if add_index is set to False and the file already exists, 
+		                               'w'/'w+' will overwrite the file, whereas 'a'/'a+' and 'r' will not.
+		    add_index (bool, optional) : indicates if an index will be given to the file's name. 
+		                                 Set it to True if you want to ensure that the opened file is a new file.
+
 
 		Return value :
-		    The opened file (same as "open(path)") if  getIndex is False
+		    The opened file (same as "open(path)")
 
 		"""
 
@@ -337,7 +351,7 @@ class Project:
 
 		return f
 
-	def add_file(self, dir, name, ext, content = ""):
+	def add_file(self, dir, name, ext, content = "", add_index = True):
 		"""Creates a new file in the directory dir of the current version.
 
 		The actual name of the file is 'name_i.ext', with name and ext being the arguments of the same name,
@@ -346,8 +360,11 @@ class Project:
 		Args :
 		    dir (str) : the name of the directory in which the file will be created. Creates it if it doesn't exists.
 		    name (str) : the name of the file, without extension. 
-		    ext (str) : the extension of the file. If it doesn't start by a point ('.'), it will be added.
+		    ext (str) : the extension of the file.
 		    content (str, optional) : a string that will be added automatically to the file on creation.
+		    add_index (bool, optional) : indicates if an index will be given to the file's name. 
+		                                 Set it to True if you want to ensure that no file of the same name 
+		                                 is overwritten on creation.
 
 		Return value :
 		    The path to the created file
@@ -356,7 +373,7 @@ class Project:
 		self.createDir(dir)
 		i = 0
 		path = self.path + dir + "/" + name
-		if ext != "" and ext[0] != ".": ext = "."+ext
+		#if ext != "" and ext[0] != ".": ext = "."+ext
 
 		while os.path.exists(path + "_" + str(i) + ext):i += 1
 		path += "_"+str(i)+ ext
@@ -369,7 +386,8 @@ class Project:
 		return path
 
 	def open_i(self, i, dir, name, ext, openType = 'a'):
-		"""Opens a file in dir with the name 'name_i.ext'.
+		"""Opens a file in dir with the name 'name_i.ext'. 
+		(The point between 'i' and 'ext' is for readability, and is not added by the method.)
 
 		Note : Use it to modify a file created previously, not to create a file at index i 
 		unless you are sure of what you are doing
@@ -384,8 +402,13 @@ class Project:
 		self.createDir(dir)
 		return open(self.path + dir + "/" + name + "_" + str(i) + ext, openType)
 
+	def read_i(self, i, dir, name, ext):
+		f = open_i(self, i, dir, name, ext, "r")
+		return f.read()
+
 	def exist_i(self, i, dir, name, ext):
-		"""Checks if the file 'name_i.ext' exists in dir."""
+		"""Checks if the file 'name_i.ext' exists in dir.
+		(The point between 'i' and 'ext' is for readability, and is not added by the method.)"""
 
 		return os.path.exists(self.path + dir + "/" + name + "_" + str(i) + ext)
 
@@ -405,3 +428,12 @@ class Project:
 		i = 0
 		while os.path.exists(self.path + dir + "/" + name + "_" + str(i) + ext): i += 1
 		return i - 1
+
+class UDGtools(object):
+	"""A set of tools to use UDG"""
+	@property # so that UDGtools() gives an error
+	def __init__(self):pass
+	
+	@staticmethod
+	def getRadius(n, h, w, md):
+		math.sqrt(h * w * md / (math.pi * n))