From a639f0833c02e7fc6c7ad2cc8423f8074bcc37bd Mon Sep 17 00:00:00 2001
From: Commandre Benjamin <benjamin.commandre@irstea.fr>
Date: Thu, 29 Nov 2018 15:33:53 +0100
Subject: [PATCH] Nettoyage du code + Optimisation

---
 PHYMOBAT.py   | 540 ++++++++++++++++++++++++++------------------------
 Processing.py | 400 +++++++++++++++++++------------------
 Sample.py     | 140 ++++++-------
 Vector.py     |  87 ++++----
 4 files changed, 590 insertions(+), 577 deletions(-)

diff --git a/PHYMOBAT.py b/PHYMOBAT.py
index ca791f8..39dbf39 100644
--- a/PHYMOBAT.py
+++ b/PHYMOBAT.py
@@ -1,18 +1,18 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
+#
 # Copyright 2016 Sylvio Laventure (IRSTEA - UMR TETIS)
 #
 # PHYMOBAT 3.0 is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation, either version 3 of the License, or
 # (at your option) any later version.
-# 
+#
 # PHYMOBAT 3.0 is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License
 # along with PHYMOBAT 3.0.  If not, see <http://www.gnu.org/licenses/>.
 
@@ -52,7 +52,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 	"""
 		Interface main class. It makes to link ``ui_PHYMOBAT_tab`` and ``Processing``.
 	"""
-	
+
 	def __init__(self, mode = Constantes.SIMPLE_MODE, parent=None):
 		super(PHYMOBAT, self).__init__(parent)
 		Processing.__init__(self)
@@ -65,8 +65,8 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 		self.current_mode = mode
 
 		self.logger = Outils.Log("Log", "Phymobat")
-		
-		# To select interface's parameters		
+
+		# To select interface's parameters
 		if self.current_mode == Constantes.EXPERT_MODE:
 			self.logger.info("Expert mode.")
 			global Ui_PHYMOBAT, _translate
@@ -75,16 +75,16 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			self.logger.info("Simple mode.")
 			global Ui_PHYMOBAT, _translate
 			from ui_PHYMOBATs_tab import Ui_PHYMOBAT, _translate
-			
+
 		self.initUI()
-		
+
 	def initUI(self):
-		
+
 		"""
 		Get initial values from interface after a click button.
-		
+
 		There is :
-		
+
 		- Connect browser button to search a path
 			* Main folder path
 			* Study area shapefile path
@@ -94,15 +94,15 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			* Output classification shapefile path
 			* Sample shapefile path
 			* Image path for samples if the first processing image hasn't been launched
-			
+
 		- Connect button to add sample in the memory list
 		- Connect button to clear sample record. Clear in the interface and in the memory list
 		- Connect close|ok button
 		- Connect menu bar tab (Open backup, save in a xml file, close, help, About PHYMOBAT, mode)
 		- Initialize backup variable
-		
+
 		"""
-					
+
 		# Initial interface
 		self.ui = Ui_PHYMOBAT()
 		self.ui.setupUi(self)
@@ -112,41 +112,41 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 		# Main folder path
 		self.ui.lineEdit_principal_folder.clear()
 		self.ui.pushButton_browser_principal_folder.clicked.connect(self.f_path_folder_dpt)
-		
+
 		# Block other function if SpotWorldHeritage is chose
 		try :
 			self.ui.comboBox_captor.currentIndexChanged.connect(self.block_for_swh)
 		except AttributeError:
 			pass
-		
+
 		# VHRS image path
 		self.ui.lineEdit_VHRS.clear()
 		self.ui.pushButton_browser_VHRS.clicked.connect(self.f_path_ortho)
-		
+
 		# Study area shapefile path
 		self.ui.lineEdit_area_path.clear()
 		self.ui.pushButton_browser_area_path.clicked.connect(self.f_path_area)
-		
+
 		# Proxy
 		self.ui.proxy.clicked.connect(self.f_proxy)
-		
+
 		# Segmentation shapefile path
 		self.ui.lineEdit_segmentation.clear()
 		self.ui.pushButton_browser_segmentation.clicked.connect(self.f_path_segm)
-		
+
 		# MNT image path
 		self.ui.lineEdit_MNT.clear()
 		self.ui.pushButton_browser_MNT.clicked.connect(self.f_path_mnt)
-		
+
 		# Output classification shapefile path
 		self.ui.lineEdit_output.clear()
 		self.ui.pushButton_browser_output.clicked.connect(self.f_output_name_moba)
-		
+
 		# Sample shapefile path.
 		# For the simply mode, RPG file sample.
 		self.ui.lineEdit_sample_path.clear()
 		self.ui.pushButton_browser_sample_path.clicked.connect(self.enter_sample_name)
-	
+
 		if self.current_mode == Constantes.SIMPLE_MODE:
 			# For the simply mode, grass/wooden file sample.
 			self.ui.lineEdit_sample_path_2.clear()
@@ -154,7 +154,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			# For the simply mode, wooden file sample.
 			self.ui.lineEdit_sample_path_3.clear()
 			self.ui.pushButton_browser_sample_path_3.clicked.connect(self.enter_sample_name_ll)
-			
+
 		# Image path for samples if the first processing image hasn't been launched
 		try:
 			self.ui.pushButton_img_sample.clicked.connect(self.img_sample_name)
@@ -167,18 +167,18 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			self.ui.pushButton_add_sample.clicked.connect(self.add_sample)
 		except AttributeError:
 			pass # Simple mode
-		
+
 		# Connect button to clear sample record. Clear in the interface and in the memory list
 		try:
 			self.ui.pushButton_clear_sample.clicked.connect(self.clear_sample)
 		except AttributeError:
 			pass # Simple mode
-		
+
 		# Connect close|ok button
 		# self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Close).clicked.connect(self.close_button)
 		self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Close).clicked.connect(self.close_button)
 		self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(self.ok_button)
-		
+
 		# Connect Menu bar
 		self.ui.actionOuvrir.triggered.connect(self.open_backup) # Open backup
 		self.ui.actionSauver.triggered.connect(self.save_backup) # Save field name on the interface
@@ -187,31 +187,31 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 		self.ui.actionA_propos_de_PHYMOBAT.triggered.connect(self.about_PHYMOBA) # About PHYMOBA
 		self.ui.actionMode_Simplifi.triggered.connect(lambda checked, mode=Constantes.SIMPLE_MODE: self.change_mode(mode)) # To open the simple apply
 		self.ui.actionMode_expert.triggered.connect(lambda checked, mode=Constantes.EXPERT_MODE: self.change_mode(mode)) # To open the expert apply
-		
+
 		self.rpg_tchek = [] # To backup rpg mode
 		self.img_sample = [] # To backup
-		
+
 		# Connect change line edit on sample path to extract fieldnames. For the simply mode, this
 		# is with RPG sample
 		self.ui.lineEdit_select_sample_fieldname_1.textChanged.connect(self.field_display_1)
 		self.ui.lineEdit_select_sample_fieldname_2.textChanged.connect(self.field_display_2)
-		
+
 		# To choose the classification method
 		if self.current_mode == Constantes.EXPERT_MODE:
 			if self.ui.radioButton_rf.isChecked():
 				self.ui.checkBox_classifier_1.setEnabled(False)
 				self.ui.checkBox_classifier_2.setEnabled(False)
-			
-			self.ui.radioButton_rf.toggled.connect(self.activate_level)   
+
+			self.ui.radioButton_rf.toggled.connect(self.activate_level)
 			self.ui.radioButton_s.toggled.connect(self.activate_level)
-		
+
 		if self.current_mode == Constantes.SIMPLE_MODE:
 			# Connect change line edit to grass/wooden sample
 			self.ui.lineEdit_select_sample_fieldname_3.textChanged.connect(self.field_display_3)
 			self.ui.lineEdit_select_sample_fieldname_4.textChanged.connect(self.field_display_4)
 			self.ui.lineEdit_select_sample_fieldname_5.textChanged.connect(self.field_display_5)
 			self.ui.lineEdit_select_sample_fieldname_6.textChanged.connect(self.field_display_6)
-		
+
 		# Change connect for classification checkboxes
 		try:
 			self.ui.checkBox_classifier_1.stateChanged.connect(self.display_one_level)
@@ -219,11 +219,11 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			self.ui.checkBox_classifier_3.stateChanged.connect(self.display_all_levels)
 		except AttributeError:
 			pass # Simple mode
-		
-	def get_variable(self):		
+
+	def get_variable(self):
 		"""
 			Add a all system value like :
-		
+
 			- Main folder path by line edit
 			- Satellite captor name by combo box
 			- Classification year by line edit
@@ -234,77 +234,77 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			- Segmentation shapefile path path by line edit
 			- Output classification shapefile path by line edit
 			- Output shapefile field name by line edit and field type by combo box
-		
+
 		"""
 		# Main folder path by line edit.
 		self.path_folder_dpt = "%s" % self.ui.lineEdit_principal_folder.text()
-		
+
 		# Satellite captor name by combo box
 		try:
 			self.captor_project = self.ui.comboBox_captor.currentText()
 		except AttributeError:
 			self.captor_project = "Landsat"
-		
+
 		# Classification year by line edit
 		self.classif_year = "%s" % self.ui.lineEdit_year_images.text()
-		
+
 		# Study area shapefile path by line edit
 		self.path_area = "%s" % self.ui.lineEdit_area_path.text()
-		
+
 		# Connexion username and password by line edit
 		self.user = "%s" % self.ui.lineEdit_user.text()
 		self.password = "%s" % self.ui.lineEdit_password.text()
-		
+
 		# VHRS image path by line edit
 		self.path_ortho = "%s" % self.ui.lineEdit_VHRS.text()
-		
+
 		# MNT image path by line edit
-		self.path_mnt = self.ui.lineEdit_MNT.text()		
-		
+		self.path_mnt = self.ui.lineEdit_MNT.text()
+
 		# Output shapefile field name by line edit and field type by combo box
 		try:
 			if self.ui.checkBox_classifier_1.isChecked() and self.ui.lineEdit_fieldname_1.text() != '':
 				self.out_fieldname_carto.append("%s" % self.ui.lineEdit_fieldname_1.text())
 				self.out_fieldtype_carto.append(eval("ogr.OFT%s" % self.ui.comboBox_fieldname_1.currentText()))
-				
+
 			if self.ui.checkBox_classifier_2.isChecked() and self.ui.lineEdit_fieldname_12.text() != '':
 				self.out_fieldname_carto.append("%s" % self.ui.lineEdit_fieldname_12.text())
 				self.out_fieldtype_carto.append(eval("ogr.OFT%s" % self.ui.comboBox_fieldname_12.currentText()))
-			
+
 				if self.ui.lineEdit_fieldname_2.text() != '':
 					self.out_fieldname_carto.append("%s" % self.ui.lineEdit_fieldname_2.text())
 					self.out_fieldtype_carto.append(eval("ogr.OFT%s" % self.ui.comboBox_fieldname_2.currentText()))
-				
+
 			if self.ui.checkBox_classifier_3.isChecked() and self.ui.lineEdit_fieldname_13.text() != '':
 				self.out_fieldname_carto.append("%s" % self.ui.lineEdit_fieldname_13.text())
 				self.out_fieldtype_carto.append(eval("ogr.OFT%s" % self.ui.comboBox_fieldname_13.currentText()))
-			
+
 				if self.ui.lineEdit_fieldname_23.text() != '':
 					self.out_fieldname_carto.append("%s" % self.ui.lineEdit_fieldname_23.text())
 					self.out_fieldtype_carto.append(eval("ogr.OFT%s" % self.ui.comboBox_fieldname_23.currentText()))
-			 
-					if self.ui.lineEdit_fieldname_3.text() != '':   
+
+					if self.ui.lineEdit_fieldname_3.text() != '':
 						self.out_fieldname_carto.append("%s" % self.ui.lineEdit_fieldname_3.text())
 						self.out_fieldtype_carto.append(eval("ogr.OFT%s" % self.ui.comboBox_fieldname_3.currentText()))
-			
-						if self.ui.lineEdit_fieldname_4.text() != '':	
+
+						if self.ui.lineEdit_fieldname_4.text() != '':
 							self.out_fieldname_carto.append("%s" % self.ui.lineEdit_fieldname_4.text())
 							self.out_fieldtype_carto.append(eval("ogr.OFT%s" % self.ui.comboBox_fieldname_4.currentText()))
 		except AttributeError:
 			modes_fieldname = ["NIVEAU_1", "NIVEAU_2", "NIVEAU_3", "POURC"]
 			modes_fieldtype = [eval("ogr.OFTString"), eval("ogr.OFTString"), eval("ogr.OFTString"), eval("ogr.OFTReal")]
-			
+
 			for mf in range(len(modes_fieldname)):
-				
+
 				self.out_fieldname_carto.append(modes_fieldname[mf])
 				self.out_fieldtype_carto.append(modes_fieldtype[mf])
-		
+
 		# Segmentation shapefile path path by line edit
 		self.path_segm = "%s" % self.ui.lineEdit_segmentation.text()
-		
+
 		# Output shapefile field name by line edit and field type by combo box
 		self.output_name_moba = "%s" % self.ui.lineEdit_output.text()
-		
+
 	def set_variable(self):
 		"""
 			Print number of available image from Theia's GeoJSON .
@@ -315,14 +315,14 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			self.ui.label_listing.setText(str(self.nb_avalaible_images))
 		except AttributeError:
 			pass # Simple mode
-		
+
 	def f_path_folder_dpt(self):
 		"""
 			Open a input browser box to select the main folder path by line edit.
 		"""
 		infoldername = QtWidgets.QFileDialog.getExistingDirectory(self, "Principal folder path", os.getcwd(), QtWidgets.QFileDialog.ShowDirsOnly)
 		self.ui.lineEdit_principal_folder.setText(str(infoldername).replace('[','').replace(']','').replace(' ',''))
-	
+
 	def block_for_swh(self):
 		"""
 			Function to block others function when SportWorldHeritage is selected in the comboxbox captor.
@@ -349,43 +349,43 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			self.ui.pushButton_browser_VHRS.setEnabled(True)
 			self.ui.tabWidget.setTabEnabled(1, True)
 			self.ui.tabWidget.setTabEnabled(2, True)
-	
+
 	def f_path_ortho(self):
 		"""
 			Open a input browser box to select the VHRS image path by line edit.
 		"""
 		orthofilename = QtWidgets.QFileDialog.getOpenFileName(self, "THRS image", self.ui.lineEdit_principal_folder.text(), '*.TIF *.tif')[0]
-		self.ui.lineEdit_VHRS.setText(str(orthofilename).replace('[','').replace(']','').replace(' ',''))   
-	
+		self.ui.lineEdit_VHRS.setText(str(orthofilename).replace('[','').replace(']','').replace(' ',''))
+
 	def f_path_mnt(self):
 		"""
 			Open a input browser box to select the MNT image path by line edit.
 		"""
 		mntfilename = QtWidgets.QFileDialog.getOpenFileName(self, "MNT image", self.ui.lineEdit_principal_folder.text(), '*.TIF *.tif')[0]
-		self.ui.lineEdit_MNT.setText(str(mntfilename).replace('[','').replace(']','').replace(' ',''))  
-		
+		self.ui.lineEdit_MNT.setText(str(mntfilename).replace('[','').replace(']','').replace(' ',''))
+
 	def f_path_area(self):
 		"""
 			Open a input browser box to select the study area shapefile path by line edit.
-		"""		
+		"""
 		areafilename = QtWidgets.QFileDialog.getOpenFileName(self, "Area shapefile", self.ui.lineEdit_principal_folder.text(), '*.shp')[0]
 		self.ui.lineEdit_area_path.setText(str(areafilename).replace('[','').replace(']','').replace(' ',''))
-		
-	def f_proxy(self):   
+
+	def f_proxy(self):
 		"""
 			Function to open a popup in order to enter proxy ID
-		""" 
+		"""
 		if self.w_proxy is None:
 			self.w_proxy = Popup.proxy_window()
 		self.w_proxy.show()
-		
+
 	def f_path_segm(self):
 		"""
 			Open a input browser box to select segmentation shapefile path path by line edit.
 		"""
 		segmfilename = QtWidgets.QFileDialog.getOpenFileName(self, "Segmentation shapefile", self.ui.lineEdit_principal_folder.text(), '*.shp')[0]
 		self.ui.lineEdit_segmentation.setText(str(segmfilename).replace('[','').replace(']','').replace(' ',''))
-	
+
 	def f_output_name_moba(self):
 		"""
 			Set the output classification shapefile path by line edit.
@@ -395,7 +395,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 		if outfilename[-4:] != '.shp':
 			outfilename = outfilename + '.shp'
 		self.ui.lineEdit_output.setText(outfilename)
-		
+
 	def enter_sample_name(self):
 		"""
 			Open a input browser box to select the sample shapefile path by line edit. With :func:`add_sample` conditions for the expert mode.
@@ -403,35 +403,35 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 		"""
 		samplefilename = QtWidgets.QFileDialog.getOpenFileName(self, "Sample shapefile", self.ui.lineEdit_principal_folder.text(), '*.shp')[0]
 		self.ui.lineEdit_sample_path.setText(str(samplefilename).replace('[','').replace(']','').replace(' ',''))
-	
+
 	def enter_sample_name_hl(self):
 		"""
-			Open a input browser box to select the grass and wooden sample shapefile path by line edit. With :func:`add_sample` conditions 
+			Open a input browser box to select the grass and wooden sample shapefile path by line edit. With :func:`add_sample` conditions
 			for the simply mode.
 		"""
 		samplefilename_hl = QtWidgets.QFileDialog.getOpenFileName(self, "Grass/Wooden sample shapefile", self.ui.lineEdit_principal_folder.text(), '*.shp')[0]
 		self.ui.lineEdit_sample_path_2.setText(str(samplefilename_hl).replace('[','').replace(']','').replace(' ',''))
-		
+
 	def enter_sample_name_ll(self):
 		"""
 			Open a input browser box to select the wooden sample shapefile path by line edit. With :func:`add_sample` conditions for the simply mode.
 		"""
 		samplefilename_ll = QtWidgets.QFileDialog.getOpenFileName(self, "Wooden sample shapefile", self.ui.lineEdit_principal_folder.text(), '*.shp')[0]
 		self.ui.lineEdit_sample_path_3.setText(str(samplefilename_ll).replace('[','').replace(']','').replace(' ',''))
-		
+
 	def img_sample_name(self):
 		"""
 			Open a input browser box to select the image for samples path by line edit. With :func:`add_sample` conditions.
 		"""
 		imgsamplefilename = QtWidgets.QFileDialog.getOpenFileName(self, "Sample image", self.ui.lineEdit_principal_folder.text(), '*.TIF')[0]
 		self.ui.lineEdit_img_sample.setText(str(imgsamplefilename).replace('[','').replace(']','').replace(' ',''))
-		
+
 	def add_sample(self):
 		"""
 			Add sample information and location to compute optimal threshold :
-		
+
 			For the expert mode (mode=1) :
-		
+
 			- Append a sample name by line Edit. *This is a check box* ``RPG``, *if the sample is RPG file. It launch the Rpg class. And append a other sample from Rpg class*.
 			- Append two existent sample field names by combobox. It will be the same. 
 			- Append sample class names by line edit. One or more for every sample.
@@ -440,14 +440,14 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			- *This check box* ``Image echantillonee``, *image path for samples if the first processing image hasn't been launched*.
 				.. note:: This is for a image with one spectral band
 			- Clear all widget field at the end.
-			
+
 			For the simply mode (mode=0):
-		
+
 			- Append a sample name by a different line Edit (a line Edit for each sample).
 			- Append sample class names, existing sample fields and number of polygons (a different line Edit for each sample)
 		"""
-		
-		nb_sample = len(self.sample_name)# Compute number of samples added. Condition : max three. 
+
+		nb_sample = len(self.sample_name)# Compute number of samples added. Condition : max three.
 
 		# Study area shapefile path by line edit if no processing other
 		# Because the function "Vector" need study area
@@ -455,24 +455,24 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 
 		if not self.path_area :
 			self.forget_study_area()
-		
+
 		if self.current_mode == Constantes.EXPERT_MODE:
 			# Expert mode
 			if nb_sample < 3 and not self.ui.lineEdit_sample_path.text().isEmpty() and  \
 					not self.ui.lineEdit_select_sample_fieldname_1.text().isEmpty() and not self.ui.lineEdit_select_sample_fieldname_2.text().isEmpty() and \
 					not self.ui.lineEdit_select_sample_class_1.text().isEmpty() and not self.ui.lineEdit_select_sample_class_2.text().isEmpty() and \
 					not self.ui.lineEdit_select_sample_nb_poly.text().isEmpty() and not self.ui.lineEdit_area_path.text().isEmpty():
-				
+
 				# Append a sample name by line Edit.
 				if self.ui.checkBox_RPG.isChecked():
-					# Check box, if the sample of the RPG file. It launch the Rpg class. And append a other sample from Rpg class 
+					# Check box, if the sample of the RPG file. It launch the Rpg class. And append a other sample from Rpg class
 					self.sample_name.append(self.i_rpg("%s" % self.ui.lineEdit_sample_path.text()))
 					self.rpg_tchek.append(1) # To backup
 					self.ui.checkBox_RPG.setChecked(False)
 				else:
 					self.sample_name.append("%s" % self.ui.lineEdit_sample_path.text())
 					self.rpg_tchek.append(0)
-				
+
 				# Append two sample field names by line edit. It must be the same.
 				self.fieldname_args.append("%s" % self.ui.lineEdit_select_sample_fieldname_1.text())
 				self.fieldname_args.append("%s" % self.ui.lineEdit_select_sample_fieldname_2.text())
@@ -481,7 +481,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				self.class_args.append("%s" % self.ui.lineEdit_select_sample_class_2.text())
 				# Append number of polygons for every samples by line edit.
 				self.list_nb_sample.append("%s" % self.ui.lineEdit_select_sample_nb_poly.text())
-				
+
 				nb_sample = len(self.sample_name) # Number of samples added
 				# Print in a plain text edit : sample name, two sample field names, sample class names and number of polygons.
 				cursor = self.ui.plainTextEdit_sample.textCursor()
@@ -497,7 +497,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				cursor.movePosition(QTextCursor.Down, QTextCursor.MoveAnchor)
 				self.ui.plainTextEdit_sample.setTextCursor(cursor)
 				self.ui.plainTextEdit_sample.insertPlainText(str(self.list_nb_sample[nb_sample-1]) + "\n")
-				
+
 				# Check box, image path for samples if the first processing image hasn't been launched
 				# Warming : This is for a image with one spectral band
 				if self.ui.checkBox_img_sample.isChecked():
@@ -508,7 +508,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 					self.img_sample.append(1)
 				else: # To backup
 					self.img_sample.append(0)
-	
+
 				# Clear all line edit after addition, ie after click add button.
 				self.ui.lineEdit_sample_path.clear()
 				self.ui.lineEdit_select_sample_fieldname_1.clear()
@@ -516,14 +516,14 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				self.ui.lineEdit_select_sample_class_1.clear()
 				self.ui.lineEdit_select_sample_class_2.clear()
 				self.ui.lineEdit_select_sample_nb_poly.clear()
-				
+
 		elif self.current_mode == Constantes.SIMPLE_MODE:
 			# Simple mode
 
 			# Append a sample name by line Edit.
-			# For the sample of the RPG file. It launch the Rpg class. And append a other sample from Rpg class 
+			# For the sample of the RPG file. It launch the Rpg class. And append a other sample from Rpg class
 			self.sample_name.append(self.i_rpg(self.ui.lineEdit_sample_path.text()))
-			
+
 			# Append two sample field names by line edit. It must be the same.
 			self.fieldname_args.append(self.ui.lineEdit_select_sample_fieldname_1.text())
 			self.fieldname_args.append(self.ui.lineEdit_select_sample_fieldname_2.text())
@@ -534,7 +534,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 
 			# Append number of polygons for every samples by line edit.
 			self.list_nb_sample.append(self.ui.lineEdit_select_sample_nb_poly.text())
-			
+
 			# Same process that the RPG process except the start of the RPG class.
 			# To Grass/wooden
 			self.sample_name.append(self.ui.lineEdit_sample_path_2.text())
@@ -543,7 +543,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			self.class_args.append(self.ui.lineEdit_select_sample_class_3.text())
 			self.class_args.append(self.ui.lineEdit_select_sample_class_4.text())
 			self.list_nb_sample.append(self.ui.lineEdit_select_sample_nb_poly_2.text())
-			
+
 			# To wooden
 			self.sample_name.append(self.ui.lineEdit_sample_path_3.text())
 			self.fieldname_args.append(self.ui.lineEdit_select_sample_fieldname_5.text())
@@ -551,7 +551,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			self.class_args.append(self.ui.lineEdit_select_sample_class_5.text())
 			self.class_args.append(self.ui.lineEdit_select_sample_class_6.text())
 			self.list_nb_sample.append(self.ui.lineEdit_select_sample_nb_poly_3.text())
-				
+
 	def clear_sample(self):
 		"""
 			Function to clear sample record. Clear in the interface and in the memory list.
@@ -562,7 +562,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 		self.list_nb_sample = []
 		self.rpg_tchek = []
 		self.img_sample = []
-		
+
 		self.ui.lineEdit_sample_path.clear()
 		self.ui.lineEdit_select_sample_fieldname_1.clear()
 		self.ui.lineEdit_select_sample_fieldname_2.clear()
@@ -578,46 +578,46 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 		self.ui.plainTextEdit_sample.insertPlainText("3 - Lingeux mixtes / denses\n")
 		self.ui.plainTextEdit_sample.insertPlainText("\n")
 		self.ui.plainTextEdit_sample.insertPlainText("\n")
-		self.ui.plainTextEdit_sample.insertPlainText("")			
-		
+		self.ui.plainTextEdit_sample.insertPlainText("")
+
 	def field_display_1(self):
 		"""
 			Function to display fieldname class 1 in the other fieldname class 2 when text changed.
 			For the simply mode, this is RPG sample.
 		"""
 		self.ui.lineEdit_select_sample_fieldname_2.setText("%s" % self.ui.lineEdit_select_sample_fieldname_1.text())
-			
+
 	def field_display_2(self):
 		"""
 			Function to display fieldname class 2 in the other fieldname class 2 when text changed.
 			For the simply mode, this is RPG sample.
 		"""
-		self.ui.lineEdit_select_sample_fieldname_1.setText("%s" % self.ui.lineEdit_select_sample_fieldname_2.text())	
-		
+		self.ui.lineEdit_select_sample_fieldname_1.setText("%s" % self.ui.lineEdit_select_sample_fieldname_2.text())
+
 	def field_display_3(self):
 		"""
 			For the grass/wooden sample, a function to display fieldname class 1 in the other fieldname class 2 when text changed.
 		"""
 		self.ui.lineEdit_select_sample_fieldname_4.setText("%s" % self.ui.lineEdit_select_sample_fieldname_3.text())
-			
+
 	def field_display_4(self):
 		"""
 			For the grass/wooden sample, a function to display fieldname class 2 in the other fieldname class 2 when text changed.
 		"""
-		self.ui.lineEdit_select_sample_fieldname_3.setText("%s" % self.ui.lineEdit_select_sample_fieldname_4.text()) 
-		
+		self.ui.lineEdit_select_sample_fieldname_3.setText("%s" % self.ui.lineEdit_select_sample_fieldname_4.text())
+
 	def field_display_5(self):
 		"""
 			For the wooden sample, a function to display fieldname class 1 in the other fieldname class 2 when text changed.
 		"""
 		self.ui.lineEdit_select_sample_fieldname_6.setText("%s" % self.ui.lineEdit_select_sample_fieldname_5.text())
-			
+
 	def field_display_6(self):
 		"""
 			For the wooden sample, a function to display fieldname class 2 in the other fieldname class 2 when text changed.
 		"""
-		self.ui.lineEdit_select_sample_fieldname_5.setText("%s" % self.ui.lineEdit_select_sample_fieldname_6.text()) 
-	
+		self.ui.lineEdit_select_sample_fieldname_5.setText("%s" % self.ui.lineEdit_select_sample_fieldname_6.text())
+
 	def activate_level(self):
 		"""
 			To activate the first levels with seath method. This is in pushing on the decision tree radio button.
@@ -630,17 +630,17 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			self.ui.checkBox_classifier_1.setEnabled(False)
 			self.ui.checkBox_classifier_2.setEnabled(False)
 			self.ui.checkBox_classifier_3.setChecked(True)
-			  
+
 	def display_one_level(self):
 		"""
 			Function to display fieldnames option to classifier one level
 		"""
 		if self.ui.checkBox_classifier_1.isChecked():
-			
+
 			# Don't checked others checkboxes
 			self.ui.checkBox_classifier_2.setChecked(False)
 			self.ui.checkBox_classifier_3.setChecked(False)
-			
+
 			# Display options filednames
 			self.ui.label_chps_1 = QtWidgets.QLabel(self.ui.tab_3)
 			self.ui.label_chps_1.setObjectName("label_chps_1")
@@ -657,36 +657,36 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			self.ui.comboBox_fieldname_1 = QtWidgets.QComboBox(self.ui.tab_3)
 			self.ui.comboBox_fieldname_1.setObjectName("comboBox_fieldname_1")
 			self.ui.gridLayout_2.addWidget(self.ui.comboBox_fieldname_1, 11, 3, 1, 1)
-	
+
 			self.ui.lineEdit_fieldname_1.setText(_translate("PHYMOBAT", "NIVEAU_1", None))
 			self.ui.comboBox_fieldname_1.addItem("String")
 			self.ui.comboBox_fieldname_1.addItem("Real")
-	
+
 			self.ui.label_chps_1.setText(_translate("PHYMOBAT", "	Champs\n"+" des entités", None))
-			self.ui.label_chps_name_1.setText(_translate("PHYMOBAT", "Nom :", None))   
-			self.ui.label_chps_type_1.setText(_translate("PHYMOBAT", "Type :", None)) 
-		 
-		if not self.ui.checkBox_classifier_1.isChecked(): 
+			self.ui.label_chps_name_1.setText(_translate("PHYMOBAT", "Nom :", None))
+			self.ui.label_chps_type_1.setText(_translate("PHYMOBAT", "Type :", None))
+
+		if not self.ui.checkBox_classifier_1.isChecked():
 			# Clear options filednames
 			try:
 				self.ui.label_chps_1.deleteLater()
 				self.ui.label_chps_name_1.deleteLater()
-				self.ui.label_chps_type_1.deleteLater()  
+				self.ui.label_chps_type_1.deleteLater()
 				self.ui.lineEdit_fieldname_1.deleteLater()
 				self.ui.comboBox_fieldname_1.deleteLater()
-			except AttributeError:	  
+			except AttributeError:
 				pass
-	
+
 	def display_two_levels(self):
 		"""
 			Function to display fieldnames option to classifier two first levels
 		"""
 		if self.ui.checkBox_classifier_2.isChecked():
-			
+
 			# Don't checked others checkboxes
 			self.ui.checkBox_classifier_1.setChecked(False)
 			self.ui.checkBox_classifier_3.setChecked(False)
-		
+
 			self.ui.label_chps_2 = QtWidgets.QLabel(self.ui.tab_3)
 			self.ui.label_chps_2.setObjectName("label_chps_2")
 			self.ui.gridLayout_2.addWidget(self.ui.label_chps_2, 13, 0, 2, 2)
@@ -695,7 +695,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			self.ui.gridLayout_2.addWidget(self.ui.lineEdit_fieldname_12, 13, 3, 1, 1)
 			self.ui.lineEdit_fieldname_2 = QtWidgets.QLineEdit(self.ui.tab_3)
 			self.ui.lineEdit_fieldname_2.setObjectName("lineEdit_fieldname_2")
-			self.ui.gridLayout_2.addWidget(self.ui.lineEdit_fieldname_2, 13, 4, 1, 1)	
+			self.ui.gridLayout_2.addWidget(self.ui.lineEdit_fieldname_2, 13, 4, 1, 1)
 			self.ui.label_chps_type_2 = QtWidgets.QLabel(self.ui.tab_3)
 			self.ui.label_chps_type_2.setObjectName("label_chps_type_2")
 			self.ui.gridLayout_2.addWidget(self.ui.label_chps_type_2, 14, 2, 1, 1)
@@ -708,46 +708,44 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			self.ui.label_chps_name_2 = QtWidgets.QLabel(self.ui.tab_3)
 			self.ui.label_chps_name_2.setObjectName("label_chps_name_2")
 			self.ui.gridLayout_2.addWidget(self.ui.label_chps_name_2, 13, 2, 1, 1)
-			
+
 			self.ui.lineEdit_fieldname_12.setText(_translate("PHYMOBAT", "NIVEAU_1", None))
 			self.ui.comboBox_fieldname_12.addItem("String")
 			self.ui.comboBox_fieldname_12.addItem("Real")
 			self.ui.lineEdit_fieldname_2.setText(_translate("PHYMOBAT", "NIVEAU_2", None))
 			self.ui.comboBox_fieldname_2.addItem("String")
 			self.ui.comboBox_fieldname_2.addItem("Real")
-			
+
 			self.ui.label_chps_type_2.setText(_translate("PHYMOBAT", "Type :", None))
 			self.ui.label_chps_2.setText(_translate("PHYMOBAT", "	Champs\n"+" des entités", None))
 			self.ui.label_chps_name_2.setText(_translate("PHYMOBAT", "Nom :", None))
-		
-		if not self.ui.checkBox_classifier_2.isChecked(): 
+
+		if not self.ui.checkBox_classifier_2.isChecked():
 			# Clear options filednames
 			try:
 				self.ui.label_chps_2.deleteLater()
 				self.ui.label_chps_name_2.deleteLater()
-				self.ui.label_chps_type_2.deleteLater()  
+				self.ui.label_chps_type_2.deleteLater()
 				self.ui.lineEdit_fieldname_12.deleteLater()
 				self.ui.comboBox_fieldname_12.deleteLater()
 				self.ui.lineEdit_fieldname_2.deleteLater()
 				self.ui.comboBox_fieldname_2.deleteLater()
-			except AttributeError:	  
+			except AttributeError:
 				pass
-		
+
 	def display_all_levels(self):
 		"""
 			Function to display fieldnames option to launch complete classification
 		"""
-		
 		if self.ui.checkBox_classifier_3.isChecked():
-			
+
 			# Don't checked others checkboxes
 			self.ui.checkBox_classifier_1.setChecked(False)
 			self.ui.checkBox_classifier_2.setChecked(False)
-		
 			self.ui.label_chps_name_3 = QtWidgets.QLabel(self.ui.tab_3)
 			self.ui.label_chps_name_3.setObjectName("label_chps_name_3")
 			self.ui.gridLayout_2.addWidget(self.ui.label_chps_name_3, 16, 2, 1, 1)
-			self.ui.label_chps_3 = QtWidgets.QLabel(self.ui.tab_3)	
+			self.ui.label_chps_3 = QtWidgets.QLabel(self.ui.tab_3)
 			self.ui.label_chps_3.setObjectName("label_chps_3")
 			self.ui.gridLayout_2.addWidget(self.ui.label_chps_3, 16, 0, 2, 2)
 			self.ui.label_chps_type_3 = QtWidgets.QLabel(self.ui.tab_3)
@@ -777,7 +775,6 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			self.ui.comboBox_fieldname_4 = QtWidgets.QComboBox(self.ui.tab_3)
 			self.ui.comboBox_fieldname_4.setObjectName("comboBox_fieldname_4")
 			self.ui.gridLayout_2.addWidget(self.ui.comboBox_fieldname_4, 17, 6, 1, 1)
-			
 			self.ui.lineEdit_fieldname_13.setText(_translate("PHYMOBAT", "NIVEAU_1", None))
 			self.ui.comboBox_fieldname_13.addItem("String")
 			self.ui.comboBox_fieldname_13.addItem("Real")
@@ -788,19 +785,19 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			self.ui.comboBox_fieldname_3.addItem("String")
 			self.ui.comboBox_fieldname_3.addItem("Real")
 			self.ui.lineEdit_fieldname_4.setText(_translate("PHYMOBAT", "POURC", None))
-			self.ui.comboBox_fieldname_4.addItem("Real")  
+			self.ui.comboBox_fieldname_4.addItem("Real")
 			self.ui.comboBox_fieldname_4.addItem("String")
-			
+
 			self.ui.label_chps_3.setText(_translate("PHYMOBAT", "	Champs\n"+" des entités", None))
 			self.ui.label_chps_type_3.setText(_translate("PHYMOBAT", "Type :", None))
 			self.ui.label_chps_name_3.setText(_translate("PHYMOBAT", "Nom :", None))
-		
-		if not self.ui.checkBox_classifier_3.isChecked(): 
+
+		if not self.ui.checkBox_classifier_3.isChecked():
 			# Clear options filednames
 			try:
 				self.ui.label_chps_3.deleteLater()
 				self.ui.label_chps_name_3.deleteLater()
-				self.ui.label_chps_type_3.deleteLater()  
+				self.ui.label_chps_type_3.deleteLater()
 				self.ui.lineEdit_fieldname_13.deleteLater()
 				self.ui.comboBox_fieldname_13.deleteLater()
 				self.ui.lineEdit_fieldname_23.deleteLater()
@@ -809,13 +806,13 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				self.ui.comboBox_fieldname_3.deleteLater()
 				self.ui.lineEdit_fieldname_4.deleteLater()
 				self.ui.comboBox_fieldname_4.deleteLater()
-			except AttributeError:	  
+			except AttributeError:
 				pass
-			
+
 	def ok_button(self):
 		"""
 			Function to launch the processing. This function take account :
-			
+
 			- The ``Multi-processing`` check box if the processing has launched with multi process.
 				By default, this is checked. It need a computer with minimum 12Go memory.
 			- Append a few system value with :func:`get_variable`.
@@ -826,127 +823,144 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				- to compute slope raster
 				- for classification processing.
 		"""
-		
 		# Start the processus
 		startTime = time.time()
-		
+
 		# To know if the processing must be launch on several thread
-		self.mp = Constantes.MULTIPROCESSING_ENABLE if self.ui.checkBox_multiprocess.isChecked() else Constantes.MULTIPROCESSING_DISABLE 
-		
+		self.mp = Constantes.MULTIPROCESSING_ENABLE if self.ui.checkBox_multiprocess.isChecked() else Constantes.MULTIPROCESSING_DISABLE
+
 		self.get_variable() # Append a few system value
 		vs = 0 # Variable to launch VHRS texture processing
-		dd = 0 # Variable to launch image downloading 
+		dd = 0 # Variable to launch image downloading
 		ok = 1 # Variable to verify informations -> 0 not ok, 1 ok
-		
+
 		if self.current_mode == Constantes.EXPERT_MODE:
 			# if download check box is checked only
-			if not self.ui.checkBox_listing.isChecked() and self.ui.checkBox_download.isChecked():		   
+			if not self.ui.checkBox_listing.isChecked() and self.ui.checkBox_download.isChecked():
 				self.ui.checkBox_listing.setChecked(True)
-				 
-			if ok == 1:	   
-				# Compute a output slope raster 
+
+			if ok == 1 :
+				# Compute a output slope raster
 				if self.ui.checkBox_MNT.isChecked():
-					self.i_slope()	   
-				
+					self.i_slope()
+
 				# Downloading and processing on theia platform
 				# A check box to get number download available images
 				if self.ui.checkBox_listing.isChecked():
-					
+
 					if self.ui.checkBox_download.isChecked():
 						# To launch the downloading
 						dd = 1
-					
+
 					self.i_download(dd) # Launch image listing and downloading if dd = 1
 					self.set_variable() # to write in the line edit about number download available images
-					
+
 					# Check box to launch the image processing
 					if self.ui.checkBox_processing.isChecked():
 						# Another check box to launch VHRS texture processing. If checked, vs = 1.
 						if self.ui.checkBox_VHRS.isChecked():
 							vs = 1
-						self.i_images_processing(vs) # function to launch the image processing			
-				
+						self.i_images_processing(vs) # function to launch the image processing
+
 				# To launch the image processing without dowloading but with the images in a main folder
 				# Without internet connection
 				if not self.ui.checkBox_download.isChecked() and self.ui.checkBox_processing.isChecked():
-					
+
 					# Launch pre-processing without downloading
 					self.i_glob()
 					# Another check box to launch VHRS texture processing. If checked, vs = 1.
 					if self.ui.checkBox_VHRS.isChecked():
 						vs = 1
 
-					self.i_images_processing(vs) # function to launch the image processing			
-				
+					self.i_images_processing(vs) # function to launch the image processing
+
 				# To launch texture processing only
 				if not self.ui.checkBox_listing.isChecked() and not self.ui.checkBox_processing.isChecked() and self.ui.checkBox_VHRS.isChecked():
-					
+
 					self.i_vhrs()
-				
-				# Compute optimal threshold  
+
+				# Compute optimal threshold
 				if self.ui.checkBox_threshold.isChecked():
-					
+
 					if self.ui.radioButton_rf.isChecked():
 						self.i_sample_rf()
 					elif self.ui.radioButton_s.isChecked():
 						self.i_sample()
-				
-				# Classification processing 
+
+				# Classification processing
 				if self.ui.radioButton_rf.isChecked():
-					
+
 					if self.ui.checkBox_classifier_3.isChecked():
-						
+
 						self.out_fieldname_carto = self.out_fieldname_carto
-						self.out_fieldtype_carto = self.out_fieldtype_carto			 
+						self.out_fieldtype_carto = self.out_fieldtype_carto
 						self.i_classifier_rf()
 						self.i_validate()
-						
+
 				elif self.ui.radioButton_s.isChecked():
-					
-					if self.ui.checkBox_classifier_1.isChecked() :		 
-						
+
+					if self.ui.checkBox_classifier_1.isChecked() :
+
 						self.out_fieldname_carto = self.out_fieldname_carto[:3]
 						self.out_fieldtype_carto = self.out_fieldtype_carto[:3]
 						self.i_classifier_s()
 						self.i_validate()
-						
+
 					if self.ui.checkBox_classifier_2.isChecked() :
-						
+
 						self.out_fieldname_carto = self.out_fieldname_carto[:4]
-						self.out_fieldtype_carto = self.out_fieldtype_carto[:4]			 
+						self.out_fieldtype_carto = self.out_fieldtype_carto[:4]
 						self.i_classifier_s()
 						self.i_validate()
-						
+
 					if self.ui.checkBox_classifier_3.isChecked():
-						
+
 						self.out_fieldname_carto = self.out_fieldname_carto
-						self.out_fieldtype_carto = self.out_fieldtype_carto			 
+						self.out_fieldtype_carto = self.out_fieldtype_carto
 						self.i_classifier_s()
 						self.i_validate()
-					
+
 		if self.current_mode == Constantes.SIMPLE_MODE:
-			
-			# Compute a output slope raster 
+
+			# Compute a output slope raster
 			if self.path_mnt :
 				self.i_slope()
 
 			# Save the sample features
 			self.add_sample()
-			
+
 			# Look at if the the images has been already downloaded, download them otherwise
 			self.i_download(self.ui.ignore_download.isChecked())
-			
-			# function to launch the image processing	
+
+			# function to launch the image processing
 			self.i_images_processing()
 
-			# Compute optimal threshold 
+			os.system("clear")
+
+			self.logger.debug("Début sample")
+
+			# Compute optimal threshold
 			self.i_sample_rf()
 
-			# Classification processing 
+			self.logger.debug("Fin sample")
+
+			os.system("clear")
+
+			self.logger.debug("Début classifier")
+
+			# Classification processing
 			self.i_classifier_rf()
 
+			self.logger.debug("Fin classifier")
+
+			os.system("clear")
+
+			self.logger.debug("Début validation")
+
 			self.i_validate()
 
+			self.logger.debug("Fin validation")
+
 		# Clear variables after processing
 		#self.clear_sample()
 		self.out_fieldname_carto = ['ID', 'AREA']
@@ -954,37 +968,37 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 
 		# Images after processing images
 		self.out_ndvistats_folder_tab = defaultdict(list)
-		
+
 		Processing.__init__(self)# Initialize variable without to close and launch again the application
-		
+
 		# End of the processus
 		endTime = time.time()
 		self.logger.info('Outputted to File in {0} secondes'.format(endTime - startTime))
 		nb_day_processing = int(time.strftime('%d', time.gmtime(endTime - startTime))) - 1
 		self.logger.info("That is {0} day(s) {1}".format(nb_day_processing, time.strftime('%Hh %Mmin%S', time.gmtime(endTime - startTime))))
-		
+
 	def open_backup(self, test=None):
 		"""
 			Function to load input text in every fields. The input file must be a XML file.
 		"""
 
 		# in_backup = QtWidgets.QFileDialog.getOpenFileName(self, "Open backup", os.getcwd(), '*.xml')[0]
-		
+
 		if test is False :
 			in_backup = QtWidgets.QFileDialog.getOpenFileName(self, "Open backup", os.getcwd(), '*.xml')[0]
 		else :
 			in_backup = test
-		
+
 		if in_backup and len(in_backup) > 0 :
 
 			# Parse the xml file if the user choose a file
 			tree = ET.parse(str(in_backup))
-			
+
 			if tree.find("Multi_process").text == '1':
 				self.ui.checkBox_multiprocess.setChecked(True)
 			else:
 				self.ui.checkBox_multiprocess.setChecked(False)
-			
+
 			pr = tree.find("Tab[@id='Processing_raster']")
 
 			try:
@@ -1002,7 +1016,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				self.logger.debug('Not year images')
 
 			self.ui.lineEdit_area_path.setText(pr.find("Area_path").text)
-			
+
 			if self.current_mode == Constantes.EXPERT_MODE:
 				if pr.find("Images_available").text == '1':
 					self.ui.checkBox_listing.setChecked(True)
@@ -1012,13 +1026,13 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 					self.ui.checkBox_download.setChecked(True)
 				else:
 					self.ui.checkBox_download.setChecked(False)
-				
+
 			try:
 				self.ui.lineEdit_user.setText(pr.find("Username").text)
 				self.ui.lineEdit_password.setText(pr.find("Password").text)
 			except:
 				self.logger.debug('Not username or password Theia')
-			
+
 			self.f_proxy()
 			try:
 				pp = pr.find("Proxy[@id='Proxy']")
@@ -1035,7 +1049,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			except AttributeError:
 				self.logger.debug('Not proxy')
 			self.w_proxy.close_window()
-				
+
 			if self.current_mode == Constantes.EXPERT_MODE:
 				if pr.find("Img_processing").text == '1':
 					self.ui.checkBox_processing.setChecked(True)
@@ -1044,25 +1058,25 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				if pr.find("VHRS_checked").text == '1':
 					self.ui.checkBox_VHRS.setChecked(True)
 				else:
-					self.ui.checkBox_VHRS.setChecked(False)	
-				
+					self.ui.checkBox_VHRS.setChecked(False)
+
 			try:
 				self.ui.lineEdit_VHRS.setText(pr.find("VHRS").text)
 			except:
 				self.logger.debug('Not VHRS image')
-				
+
 			if self.current_mode == Constantes.EXPERT_MODE:
 				if pr.find("MNT_checked").text == '1':
 					self.ui.checkBox_MNT.setChecked(True)
 				else:
-					self.ui.checkBox_MNT.setChecked(False)	
-				
+					self.ui.checkBox_MNT.setChecked(False)
+
 			try:
 				self.ui.lineEdit_MNT.setText(pr.find("MNT").text)
 			except:
 				self.logger.debug('Not MNT')
-				
-			ps = tree.find("Tab[@id='Processing_sample']")  
+
+			ps = tree.find("Tab[@id='Processing_sample']")
 			if self.current_mode == Constantes.EXPERT_MODE:
 				try:
 					for sple_n in ps.iter("Sample"):
@@ -1085,7 +1099,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 						self.add_sample()
 				except:
 					self.logger.debug('Not sample')
-			
+
 			elif self.current_mode == Constantes.SIMPLE_MODE:
 				# RPG
 				sple_n = ps[0]
@@ -1095,7 +1109,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				self.ui.lineEdit_select_sample_class_1.setText(sple_n.find("Classname_1").text)
 				self.ui.lineEdit_select_sample_class_2.setText(sple_n.find("Classname_2").text)
 				self.ui.lineEdit_select_sample_nb_poly.setText(sple_n.find("Nb_polygones").text)
-				
+
 				# To Grass/wooden
 				sple_n = ps[1]
 				self.ui.lineEdit_sample_path_2.setText(sple_n.find("Sample_path").text)
@@ -1103,8 +1117,8 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				self.ui.lineEdit_select_sample_fieldname_4.setText(sple_n.find("Fieldname_2").text)
 				self.ui.lineEdit_select_sample_class_3.setText(sple_n.find("Classname_1").text)
 				self.ui.lineEdit_select_sample_class_4.setText(sple_n.find("Classname_2").text)
-				self.ui.lineEdit_select_sample_nb_poly_2.setText(sple_n.find("Nb_polygones").text)		
-				
+				self.ui.lineEdit_select_sample_nb_poly_2.setText(sple_n.find("Nb_polygones").text)
+
 				# To wooden
 				sple_n = ps[2]
 				self.ui.lineEdit_sample_path_3.setText(sple_n.find("Sample_path").text)
@@ -1113,13 +1127,13 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				self.ui.lineEdit_select_sample_class_5.setText(sple_n.find("Classname_1").text)
 				self.ui.lineEdit_select_sample_class_6.setText(sple_n.find("Classname_2").text)
 				self.ui.lineEdit_select_sample_nb_poly_3.setText(sple_n.find("Nb_polygones").text)
-					
+
 			if self.current_mode == Constantes.EXPERT_MODE:
 				if ps.find("Threshold_checked").text == '1':
 					self.ui.checkBox_threshold.setChecked(True)
 				else:
-					self.ui.checkBox_threshold.setChecked(False) 
-			 
+					self.ui.checkBox_threshold.setChecked(False)
+
 			c = tree.find("Tab[@id='Classification']")
 
 			try:
@@ -1136,15 +1150,15 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				if len(c) == 5:
 					self.ui.checkBox_classifier_1.setChecked(True)
 					self.ui.lineEdit_fieldname_1.setText(c.find("Output_fieldname_1").text)
-					index_fieldname_1 = self.ui.comboBox_fieldname_1.findText(c.find("Output_type_1").text)		
+					index_fieldname_1 = self.ui.comboBox_fieldname_1.findText(c.find("Output_type_1").text)
 					self.ui.comboBox_fieldname_1.setCurrentIndex(index_fieldname_1)
 				elif len(c) == 7:
 					self.ui.checkBox_classifier_2.setChecked(True)
 					self.ui.lineEdit_fieldname_12.setText(c.find("Output_fieldname_1").text)
 					self.ui.lineEdit_fieldname_2.setText(c.find("Output_fieldname_2").text)
-					index_fieldname_12 = self.ui.comboBox_fieldname_12.findText(c.find("Output_type_1").text)		
+					index_fieldname_12 = self.ui.comboBox_fieldname_12.findText(c.find("Output_type_1").text)
 					self.ui.comboBox_fieldname_12.setCurrentIndex(index_fieldname_12)
-					index_fieldname_2 = self.ui.comboBox_fieldname_2.findText(c.find("Output_type_2").text)		
+					index_fieldname_2 = self.ui.comboBox_fieldname_2.findText(c.find("Output_type_2").text)
 					self.ui.comboBox_fieldname_2.setCurrentIndex(index_fieldname_2)
 				elif len(c) == 11:
 					self.ui.checkBox_classifier_3.setChecked(True)
@@ -1152,43 +1166,43 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 					self.ui.lineEdit_fieldname_23.setText(c.find("Output_fieldname_2").text)
 					self.ui.lineEdit_fieldname_3.setText(c.find("Output_fieldname_3").text)
 					self.ui.lineEdit_fieldname_4.setText(c.find("Output_fieldname_4").text)
-					index_fieldname_13 = self.ui.comboBox_fieldname_13.findText(c.find("Output_type_1").text)		
+					index_fieldname_13 = self.ui.comboBox_fieldname_13.findText(c.find("Output_type_1").text)
 					self.ui.comboBox_fieldname_13.setCurrentIndex(index_fieldname_13)
-					index_fieldname_23 = self.ui.comboBox_fieldname_23.findText(c.find("Output_type_2").text)		
+					index_fieldname_23 = self.ui.comboBox_fieldname_23.findText(c.find("Output_type_2").text)
 					self.ui.comboBox_fieldname_23.setCurrentIndex(index_fieldname_23)
-					index_fieldname_3 = self.ui.comboBox_fieldname_3.findText(c.find("Output_type_3").text)		
+					index_fieldname_3 = self.ui.comboBox_fieldname_3.findText(c.find("Output_type_3").text)
 					self.ui.comboBox_fieldname_3.setCurrentIndex(index_fieldname_3)
-					index_fieldname_4 = self.ui.comboBox_fieldname_4.findText(c.find("Output_type_4").text)		
+					index_fieldname_4 = self.ui.comboBox_fieldname_4.findText(c.find("Output_type_4").text)
 					self.ui.comboBox_fieldname_4.setCurrentIndex(index_fieldname_4)
-				
+
 				# Classification mode
 				if c.find("Classification_method").text == '1':
 					self.ui.radioButton_rf.setChecked(True)
 				else:
 					self.ui.radioButton_s.setChecked(True)
-					   
+
 	def save_backup(self):
 		"""
 			Function to save input text in every fields.
 			The output file must be a XML file.
 		"""
-		
+
 		out_backup = QtWidgets.QFileDialog.getSaveFileName(self, "Save backup", os.getcwd(), '*.xml')[0]
 
 		# if the user has forgotten to put .shp at the end of the output xml
 		if not out_backup.endswith('.xml'):
 			out_backup = out_backup + '.xml'
-		
+
 		root = ET.Element("Data_filled")
-		
+
 		if self.ui.checkBox_multiprocess.isChecked():
 			ET.SubElement(root, "Multi_process", type = "int").text = str(1)
 		else:
 			ET.SubElement(root, "Multi_process", type = "int").text = str(0)
-		
+
 		doc = ET.SubElement(root, "Tab", id="Processing_raster")
 		ET.SubElement(doc, "Principal_folder", type = "str").text = "%s" % self.ui.lineEdit_principal_folder.text()
-		
+
 		if self.current_mode == Constantes.EXPERT_MODE:
 			ET.SubElement(doc, "Captor", type = "str").text = "%s" % self.ui.comboBox_captor.currentText()
 		else:
@@ -1196,7 +1210,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 
 		ET.SubElement(doc, "Year_images", type = "str").text = "%s" % self.ui.lineEdit_year_images.text()
 		ET.SubElement(doc, "Area_path", type = "str").text = "%s" % self.ui.lineEdit_area_path.text()
-		
+
 		if self.current_mode == Constantes.EXPERT_MODE:
 			if self.ui.checkBox_listing.isChecked():
 				ET.SubElement(doc, "Images_available", type = "int").text = str(1)
@@ -1209,7 +1223,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 		else:
 			ET.SubElement(doc, "Images_available", type = "int").text = str(0)
 			ET.SubElement(doc, "Download", type = "int").text = str(0)
-			
+
 		ET.SubElement(doc, "Username", type = "str").text = "%s" % self.ui.lineEdit_user.text()
 		ET.SubElement(doc, "Password", type = "str").text = "%s" % self.ui.lineEdit_password.text()
 		if self.w_proxy is None:
@@ -1227,13 +1241,13 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			ET.SubElement(sub_proxy, "Proxy_adress", type = "str").text = "%s" % self.w_proxy.proxy
 			ET.SubElement(sub_proxy, "Proxy_login", type = "str").text = "%s" % self.w_proxy.login_proxy
 			ET.SubElement(sub_proxy, "Proxy_password", type = "str").text = "%s" % self.w_proxy.password_proxy
-		
+
 		if self.current_mode == Constantes.EXPERT_MODE:
 			if self.ui.checkBox_processing.isChecked():
 				ET.SubElement(doc, "Img_processing", type = "int").text = str(1)
 			else:
 				ET.SubElement(doc, "Img_processing", type = "int").text = str(0)
-			
+
 			if self.ui.checkBox_VHRS.isChecked():
 				ET.SubElement(doc, "VHRS_checked", type = "int").text = str(1)
 			else:
@@ -1241,9 +1255,9 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 		else:
 			ET.SubElement(doc, "Img_processing", type = "int").text = str(1)
 			ET.SubElement(doc, "VHRS_checked", type = "int").text = str(1)
-			
+
 		ET.SubElement(doc, "VHRS", type = "str").text = "%s" % self.ui.lineEdit_VHRS.text()
-		
+
 		if self.current_mode == Constantes.EXPERT_MODE:
 			if self.ui.checkBox_MNT.isChecked():
 				ET.SubElement(doc, "MNT_checked", type = "int").text = str(1)
@@ -1254,9 +1268,9 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				ET.SubElement(doc, "MNT_checked", type = "int").text = str(1)
 			else:
 				ET.SubElement(doc, "MNT_checked", type = "int").text = str(0)
-			
+
 		ET.SubElement(doc, "MNT", type = "str").text = "%s" % self.ui.lineEdit_MNT.text()
-		
+
 		doc = ET.SubElement(root, "Tab", id="Processing_sample")
 		if self.current_mode == Constantes.EXPERT_MODE:
 			for sa in range(len(self.sample_name)):
@@ -1269,11 +1283,11 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				ET.SubElement(sub_doc, "Nb_polygones", type = "str").text = self.list_nb_sample[sa]
 				ET.SubElement(sub_doc, "RPG", type = "int").text = str(self.rpg_tchek[sa])
 				try:
-					# To enter a sample raster if the first tab doesn't launch before 
+					# To enter a sample raster if the first tab doesn't launch before
 					if self.img_sample[sa] == 1:
 						ET.SubElement(sub_doc, "Img_sample", type = "str").text = self.raster_path[sa]
 				except:
-					self.logger.debug('Not sample raster only !')   
+					self.logger.debug('Not sample raster only !')
 		else:
 			# RPG
 			sub_doc = ET.SubElement(doc, "Sample", id="Sample_0")
@@ -1284,7 +1298,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			ET.SubElement(sub_doc, "Classname_2", type = "str").text = "%s" % self.ui.lineEdit_select_sample_class_2.text()
 			ET.SubElement(sub_doc, "Nb_polygones", type = "str").text = "%s" % self.ui.lineEdit_select_sample_nb_poly.text()
 			ET.SubElement(sub_doc, "RPG", type = "int").text = str(1)
-			
+
 			# To Grass/wooden
 			sub_doc = ET.SubElement(doc, "Sample", id="Sample_1")
 			ET.SubElement(sub_doc, "Sample_path", type = "str").text = "%s" % self.ui.lineEdit_sample_path_2.text()
@@ -1294,8 +1308,8 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			ET.SubElement(sub_doc, "Classname_2", type = "str").text = "%s" % self.ui.lineEdit_select_sample_class_4.text()
 			ET.SubElement(sub_doc, "Nb_polygones", type = "str").text = "%s" % self.ui.lineEdit_select_sample_nb_poly_2.text()
 			ET.SubElement(sub_doc, "RPG", type = "int").text = str(0)
-			
-			# To wooden  
+
+			# To wooden
 			sub_doc = ET.SubElement(doc, "Sample", id="Sample_2")
 			ET.SubElement(sub_doc, "Sample_path", type = "str").text = "%s" % self.ui.lineEdit_sample_path_3.text()
 			ET.SubElement(sub_doc, "Fieldname_1", type = "str").text = "%s" % self.ui.lineEdit_select_sample_fieldname_5.text()
@@ -1303,8 +1317,8 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			ET.SubElement(sub_doc, "Classname_1", type = "str").text = "%s" % self.ui.lineEdit_select_sample_class_5.text()
 			ET.SubElement(sub_doc, "Classname_2", type = "str").text = "%s" % self.ui.lineEdit_select_sample_class_6.text()
 			ET.SubElement(sub_doc, "Nb_polygones", type = "str").text = "%s" % self.ui.lineEdit_select_sample_nb_poly_3.text()
-			ET.SubElement(sub_doc, "RPG", type = "int").text = str(0) 
-		
+			ET.SubElement(sub_doc, "RPG", type = "int").text = str(0)
+
 		if self.current_mode == Constantes.EXPERT_MODE:
 			if self.ui.checkBox_threshold.isChecked():
 				ET.SubElement(doc, "Threshold_checked", type = "int").text = str(1)
@@ -1312,33 +1326,33 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				ET.SubElement(doc, "Threshold_checked", type = "int").text = str(0)
 		else:
 			ET.SubElement(doc, "Threshold_checked", type = "int").text = str(1)
-			
+
 		doc = ET.SubElement(root, "Tab", id="Classification")
 		ET.SubElement(doc, "Segmentation_path", type = "str").text = "%s" % self.ui.lineEdit_segmentation.text()
 		ET.SubElement(doc, "Output_path", type = "str").text = "%s" % self.ui.lineEdit_output.text()
-		
+
 		if self.current_mode == Constantes.EXPERT_MODE:
-				
+
 			if self.ui.checkBox_classifier_1.isChecked():
 				ET.SubElement(doc, "Output_fieldname_1", type = "str").text = "%s" % self.ui.lineEdit_fieldname_1.text()
 				ET.SubElement(doc, "Output_type_1", type = "str").text = "%s" % self.ui.comboBox_fieldname_1.currentText()
-			 
+
 			if self.ui.checkBox_classifier_2.isChecked():
 				ET.SubElement(doc, "Output_fieldname_1", type = "str").text = "%s" % self.ui.lineEdit_fieldname_12.text()
-				ET.SubElement(doc, "Output_type_1", type = "str").text = "%s" % self.ui.comboBox_fieldname_12.currentText()	
+				ET.SubElement(doc, "Output_type_1", type = "str").text = "%s" % self.ui.comboBox_fieldname_12.currentText()
 				ET.SubElement(doc, "Output_fieldname_2", type = "str").text = "%s" % self.ui.lineEdit_fieldname_2.text()
 				ET.SubElement(doc, "Output_type_2", type = "str").text = "%s" % self.ui.comboBox_fieldname_2.currentText()
-			
+
 			if self.ui.checkBox_classifier_3.isChecked():
 				ET.SubElement(doc, "Output_fieldname_1", type = "str").text = "%s" % self.ui.lineEdit_fieldname_13.text()
-				ET.SubElement(doc, "Output_type_1", type = "str").text = "%s" % self.ui.comboBox_fieldname_13.currentText()	
+				ET.SubElement(doc, "Output_type_1", type = "str").text = "%s" % self.ui.comboBox_fieldname_13.currentText()
 				ET.SubElement(doc, "Output_fieldname_2", type = "str").text = "%s" % self.ui.lineEdit_fieldname_23.text()
 				ET.SubElement(doc, "Output_type_2", type = "str").text = "%s" % self.ui.comboBox_fieldname_23.currentText()
 				ET.SubElement(doc, "Output_fieldname_3", type = "str").text = "%s" % self.ui.lineEdit_fieldname_3.text()
 				ET.SubElement(doc, "Output_type_3", type = "str").text = "%s" % self.ui.comboBox_fieldname_3.currentText()
 				ET.SubElement(doc, "Output_fieldname_4", type = "str").text = "%s" % self.ui.lineEdit_fieldname_4.text()
 				ET.SubElement(doc, "Output_type_4", type = "str").text = "%s" % self.ui.comboBox_fieldname_4.currentText()
-			
+
 			# Classification mode
 			if self.ui.radioButton_rf.isChecked():
 				ET.SubElement(doc, "Classification_method", type = "int").text = str(1)
@@ -1346,7 +1360,7 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 				ET.SubElement(doc, "Classification_method", type = "int").text = str(0)
 		else:
 			ET.SubElement(doc, "Output_fieldname_1", type = "str").text = "NIVEAU_1"
-			ET.SubElement(doc, "Output_type_1", type = "str").text = "String"   
+			ET.SubElement(doc, "Output_type_1", type = "str").text = "String"
 			ET.SubElement(doc, "Output_fieldname_2", type = "str").text = "NIVEAU_2"
 			ET.SubElement(doc, "Output_type_2", type = "str").text = "String"
 			ET.SubElement(doc, "Output_fieldname_3", type = "str").text = "NIVEAU_3"
@@ -1354,17 +1368,17 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			ET.SubElement(doc, "Output_fieldname_4", type = "str").text = "POURC"
 			ET.SubElement(doc, "Output_type_4", type = "str").text = "Real"
 			ET.SubElement(doc, "Classification_method", type = "int").text = str(1)
-			
+
 		tree = ET.ElementTree(root)
 		# Write in a xml file
 		tree.write(str(out_backup), encoding="UTF-8",xml_declaration=True, pretty_print=True)
-		
+
 	def help_tools(self):
 		"""
 			Function to open html help
 		"""
 		webbrowser.open('file://' + os.getcwd() + '/Documentation/methode_tuto.html#tutoriels-interface')
-	
+
 
 	def change_mode(self, new_mode):
 		"""
@@ -1393,23 +1407,23 @@ class PHYMOBAT(QtWidgets.QMainWindow, Processing):
 			Function to open a new window 'Alert' because user forgotten to declare study area.
 		"""
 		self.w_study_area.show()
-		
+
 	def forget_raster_sample(self):
 		"""
 			Function to open a new window 'Alert' because user forgotten to declare rasters or samples.
-		"""			
+		"""
 		self.w_forget.show()
-				
+
 	def close_button(self):
 		"""
 			Function to close the interface.
 		"""
 		self.close()
-		
+
 if __name__ == "__main__":
-	
+
 	app = QtWidgets.QApplication(sys.argv)
 	myapp = PHYMOBAT()
 	myapp.show()
-		
+
 	sys.exit(app.exec_())
diff --git a/Processing.py b/Processing.py
index 9d833cb..218d330 100644
--- a/Processing.py
+++ b/Processing.py
@@ -3,17 +3,17 @@
 #
 # This file is part of PHYMOBAT 2.0.
 # Copyright 2016 Sylvio Laventure (IRSTEA - UMR TETIS)
-# 
+#
 # PHYMOBAT 2.0 is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation, either version 3 of the License, or
 # (at your option) any later version.
-# 
+#
 # PHYMOBAT 2.0 is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License
 # along with PHYMOBAT 2.0.  If not, see <http://www.gnu.org/licenses/>.
 
@@ -22,6 +22,7 @@ import numpy as np
 import subprocess
 from sklearn.ensemble import RandomForestClassifier
 from sklearn import tree
+import pydot
 
 try :
 	import ogr, gdal
@@ -52,19 +53,18 @@ from multiprocessing import Process
 from multiprocessing.managers import BaseManager, DictProxy
 
 class Processing(object):
-	
 	"""
 		Main processing. This class launch the others system classes. It take into account
-		CarHab classification method MOBA. 
-		
+		CarHab classification method MOBA.
+
 		This way is broken down into 3 parts :
 			- Image Processing (Search, download and processing)
 			- Vector Processing (Optimal threshold, Sample processing)
-			- Classification 
-			- Validation 
-		
+			- Classification
+			- Validation
+
 		**Main parameters**
-		
+
 		:param captor_project: Satellite captor name
 		:type captor_project: str
 		:param classif_year: Classification year
@@ -83,25 +83,25 @@ class Processing(object):
 		:type path_mnt: str
 		:param path_segm: Segmentation shapefile
 		:type path_segm: str
-		
+
 		**Id information to download on theia platform**
-		
+
 		:param user: Connexion Username
 		:type user: str
 		:param password: Connexion Password
 		:type password: str
-		
+
 		**Output parameters**
-		
+
 		:param output_name_moba: Output classification shapefile 
 		:type output_name_moba: str
 		:param out_fieldname_carto: Output shapefile field name
 		:type out_fieldname_carto: list of str
 		:param out_fieldtype_carto: Output shapefile field type
 		:type out_fieldtype_carto: list of str (eval ogr pointer)
-		
+
 		**Sample parameters**
-		
+
 		:param fieldname_args: Sample field names 2 by 2
 		:type fieldname_args: list of str
 		:param class_args: Sample class names 2 by 2
@@ -110,18 +110,18 @@ class Processing(object):
 		:type sample_name: list of str
 		:param list_nb_sample: Number of polygons for every sample
 		:type list_nb_sample: list of int
-		
+
 		**Multi-processing parameters**
-		
+
 		:param mp: Boolean variable -> 0 or 1.
-		
+
 				- 0 means, not multi-processing
 				- 1 means, launch process with multi-processing
 		:type mp: int
 	"""
-	
+
 	def __init__(self):
-		
+
 		# Used variables
 		self.captor_project = ''
 		self.classif_year = ''
@@ -132,16 +132,16 @@ class Processing(object):
 		self.path_mnt = ''
 		self.path_segm = ''
 		self.output_name_moba = ''
-		
+
 		self.w_proxy = None # For the "Proxy window"
-		
+
 		# Id information to download on theia platform
 		self.user = ''
 		self.password = ''
 
 		# List of output raster path
 		self.raster_path = defaultdict(dict)
-		
+
 		# TODO : Change index of the classes -> Harbacées 6 / Ligneux 7 by Agriculuture 4 / Eboulis 5
 		# Class name
 		self.in_class_name = ['Non Vegetation semi-naturelle', 'Vegetation semi-naturelle',\
@@ -149,7 +149,7 @@ class Processing(object):
 						 'Ligneux mixtes', 'Ligneux denses',\
 						 'Agriculture', 'Eboulis', \
 						 'Forte phytomasse', 'Moyenne phytomasse', 'Faible phytomasse']
-		
+
 		# Sample field names 2 by 2
 		self.fieldname_args = []
 		#	'CODE_GROUP', 'CODE_GROUP',\
@@ -161,7 +161,7 @@ class Processing(object):
 		#	'1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 14, 15, 20, 21, 22, 23, 24, 26, 28', '18',\
 		#	'H','LF, LO',\
 		#	'LF', 'LO']
-		
+
 		# Decision tree combination
 		self.tree_direction = [[0],\
 						  [0],\
@@ -173,105 +173,104 @@ class Processing(object):
 									# ..., ['Semi-naturelles', 'Ligneux', 'Ligneux denses']]
 		# Slope degrees
 		self.slope_degree = 30
-		
+
 		# Output shapefile field name
 		self.out_fieldname_carto = ['ID', 'AREA'] #, 'NIVEAU_1', 'NIVEAU_2', 'NIVEAU_3', 'POURC']
 		# Output shapefile field type
 		self.out_fieldtype_carto = [ogr.OFTString, ogr.OFTReal] #, ogr.OFTString, ogr.OFTString, ogr.OFTString, ogr.OFTReal]
-		
+
 		# List of sample name path
 		self.sample_name = []
 		# List of number sample
 		self.list_nb_sample = []
 		# Number download available images
 		self.nb_avalaible_images = 0
-		
+
 		# Multi-processing variable
 		self.mp = Constantes.MULTIPROCESSING_DISABLE
-		
+
 		# Function followed
 		self.check_download = None
 		self.decis = {}
 
 		# Images after processing images
 		self.out_ndvistats_folder_tab = defaultdict(list)
-		
+
 		# Validation shapefiles information
 		self.valid_shp = []
-		
+
 		# Radom Forest Model
-		# Set the parameters of this random forest from the estimator 
+		# Set the parameters of this random forest from the estimator
 		self.rf = RandomForestClassifier(n_estimators=500, criterion='gini', max_depth=None, min_samples_split=2, \
 										min_samples_leaf=1, max_features='auto', \
 										bootstrap=True, oob_score=True)
-		
-	def i_tree_direction(self):	
+
+	def i_tree_direction(self):
 		"""
-			Interface function to can extract one level or two levels of the final classification 
+			Interface function to can extract one level or two levels of the final classification
 		"""
 
 		if len(self.out_fieldname_carto) == 3:
 			self.tree_direction = [[0], [1]]
-			
+
 		if len(self.out_fieldname_carto) == 4:
 			self.tree_direction = [[0], [0], [1, 2], [1, 3]]
-		
+
 	def i_download(self, ignore_download=False):
 		"""
-			Interface function to download archives on the website Theia Land. This function extract 
+			Interface function to download archives on the website Theia Land. This function extract
 			the number of downloadable image with :func:`Archive.Archive.listing`.
-			
+
 			Then, this function download :func:`Archive.Archive.download` and unzip :func:`Archive.Archive.decompress` images
 			in the archive folder (**folder_archive**).
 		"""
-		
+
 		folder_archive = "{0}/{1}_PoleTheia".format(self.folder_processing, self.captor_project)
 
 		if not os.path.exists(folder_archive) :
 			os.makedirs(folder_archive)
 
 		self.check_download = Archive(self.captor_project, self.classif_year, self.path_area, folder_archive, self.w_proxy)
-		
+
 		if not ignore_download :
 			self.nb_avalaible_images = self.check_download.listing()
 			self.check_download.download_auto(self.user, self.password)
-		
+
 		self.check_download.decompress()
 
-	def i_img_sat(self):	
+	def i_img_sat(self):
 		"""
 			Interface function to processing satellite images:
-			
+
 				1. Clip archive images and modify Archive class to integrate clip image path.
 				With :func:`Toolbox.clip_raster` in ``Toolbox`` module.
-			
-				2. Search cloud's percentage :func:`RasterSat_by_date.RasterSat_by_date.pourc_cloud`, 
+
+				2. Search cloud's percentage :func:`RasterSat_by_date.RasterSat_by_date.pourc_cloud`,
 				select image and compute ndvi index :func:`RasterSat_by_date.RasterSat_by_date.calcul_ndvi`.
 				If cloud's percentage is greater than 40%, then not select and compute ndvi index.
-			
-				3. Compute temporal stats on ndvi index [min, max, std, min-max]. With :func:`Toolbox.calc_serie_stats` 
+
+				3. Compute temporal stats on ndvi index [min, max, std, min-max]. With :func:`Toolbox.calc_serie_stats`
 				in ``Toolbox`` module.
-				
 				4. Create stats ndvi raster and stats cloud raster.
-				
+
 				>>> import RasterSat_by_date
 				>>> stats_test = RasterSat_by_date(class_archive, big_folder, one_date)
 				>>> stats_test.complete_raster(stats_test.create_raster(in_raster, stats_data, in_ds), stats_data)
 		"""
-		
+
 		current_list = Toolbox()
 		current_list.vect = self.path_area
 
 		# Map projection of the image and the cloud mask
 		for clip_index, clip in enumerate(self.check_download.list_img):
-			
+
 			current_list.image = clip[3]
-			
-			current_list.check_proj() # Check if projection is RFG93 
+
+			current_list.check_proj() # Check if projection is RFG93
 			self.check_download.list_img[clip_index][3] = current_list.clip_raster() # Multispectral images
-			
+
 			current_list.image = clip[4]
-			current_list.check_proj() # Check if projection is RFG93 
+			current_list.check_proj() # Check if projection is RFG93
 
 			self.check_download.list_img[clip_index][4] = current_list.clip_raster() # Cloud images
 
@@ -283,8 +282,8 @@ class Processing(object):
 		for date in self.check_download.single_date:
 
 			check_L8.mosaic_by_date(date)
-			 
-			# Search cloud's percentage, select image and compute ndvi index 
+
+			# Search cloud's percentage, select image and compute ndvi index
 			if check_L8.pourc_cloud() < Constantes.CLOUD_THRESHOLD :
 				tmp = date
 				check_L8.calcul_ndvi()
@@ -294,7 +293,7 @@ class Processing(object):
 		# Compute temporal stats on ndvi index [min, max, std, min-max]
 		spectral_trans = np.transpose(np.array(spectral_out, dtype=object))
 
-		del spectral_out 
+		del spectral_out
 
 		# stats_name = ['Min', 'Date', 'Max', 'Std', 'MaxMin']
 		stats_name = ['Min', 'Max']
@@ -311,12 +310,12 @@ class Processing(object):
 			Interface function to processing slope raster. From a MNT, and with a command line gdal,
 			this function compute slope in degrees :func:`Slope.Slope`.
 		"""
-		
+
 		current_path_mnt = Toolbox()
 		current_path_mnt.image = self.path_mnt
 		current_path_mnt.vect = self.path_area
 		path_mnt = current_path_mnt.clip_raster()
-		
+
 		study_slope = Slope(path_mnt)
 
 		# Call this function to compute slope raster
@@ -324,27 +323,27 @@ class Processing(object):
 		self.path_mnt = study_slope.out_mnt
 
 		current_path_mnt.logger.close()
-	
+
 	def i_vhrs(self):
 		"""
-			Interface function to processing VHRS images. 
-			It create two OTB texture images : 
+			Interface function to processing VHRS images.
+			It create two OTB texture images :
 				func: `Vhrs.Vhrs` : SFS Texture and Haralick Texture
 		"""
 
 		############################## Create texture image ##############################
-		
-		# Clip orthography image 
+
+		# Clip orthography image
 
 		current_path_ortho = Toolbox()
 
 		current_path_ortho.image = self.path_ortho
 		current_path_ortho.vect = self.path_area
 		current_path_ortho.output = "{0}/MosaiqueOrtho/Clip_{1}".format(self.folder_processing, os.path.basename(self.path_ortho))
-		
+
 		self.path_ortho = current_path_ortho.output
 		path_ortho = current_path_ortho.clip_raster()
-		
+
 		texture_irc = Vhrs(path_ortho, self.mp)
 		self.out_ndvistats_folder_tab['sfs']      = texture_irc.out_sfs
 		self.out_ndvistats_folder_tab['haralick'] = texture_irc.out_haralick
@@ -352,10 +351,10 @@ class Processing(object):
 		current_path_ortho.logger.close()
 		texture_irc.logger.close()
 
-		
-	def i_images_processing(self): 
+
+	def i_images_processing(self):
 		"""
-			Interface function to launch processing VHRS images : func:`i_vhrs` 
+			Interface function to launch processing VHRS images : func:`i_vhrs`
 			and satellite images :func:`i_img_sat` in multi-processing.
 		"""
 
@@ -365,18 +364,18 @@ class Processing(object):
 		mgr.register('defaultdict', defaultdict, DictProxy)
 		mgr.start()
 
-		self.out_ndvistats_folder_tab = mgr.defaultdict(list)		
-		
+		self.out_ndvistats_folder_tab = mgr.defaultdict(list)
+
 		p_img_sat = Process(target=self.i_img_sat)
 		p_vhrs = Process(target=self.i_vhrs)
 
 		self.logger.debug("Multiprocessing : {0}".format(self.mp))
-		
+
 		if self.mp == Constantes.MULTIPROCESSING_DISABLE:
 			p_img_sat.start()
 			p_img_sat.join()
 			p_vhrs.start()
-			p_vhrs.join()	
+			p_vhrs.join()
 		else :
 			p_img_sat.start()
 			p_vhrs.start()
@@ -387,7 +386,7 @@ class Processing(object):
 
 		self.raster_path["Min"]["PATH"] = self.out_ndvistats_folder_tab['Min']
 		self.raster_path["Min"]["BAND"] = 1
-		
+
 		for i in range(1,7) :
 			self.raster_path["SFS_{0}".format(i)]["PATH"] = self.out_ndvistats_folder_tab['sfs']
 			self.raster_path["SFS_{0}".format(i)]["BAND"] = i
@@ -395,24 +394,24 @@ class Processing(object):
 		for i in range(1,9) :
 			self.raster_path["HARALICK_{0}".format(i)]["PATH"] = self.out_ndvistats_folder_tab['haralick']
 			self.raster_path["HARALICK_{0}".format(i)]["BAND"] = i
-		
+
 		# To slope, to extract scree
 		if self.path_mnt :
 			self.raster_path["MNT"]["PATH"] = self.path_mnt
 			self.raster_path["MNT"]["BAND"] = 1
-			
+
 		self.raster_path["MAX"]["PATH"] = self.out_ndvistats_folder_tab['Max']
 		self.raster_path["MAX"]["BAND"] = 1
-		
+
 		self.logger.info("End of images processing !")
-		
-	def i_rpg(self, path_rpg): 
+
+	def i_rpg(self, path_rpg):
 		"""
 			Interface function to extract mono rpg crops.
-			
+
 			@param path_rpg: Input RPG shapefile.
 			@type path_rpg: str
-			
+
 			@returns: str -- variable **Rpg.vector_used**, output no duplicated crops shapefile (path).
 		"""
 
@@ -420,10 +419,10 @@ class Processing(object):
 			format(self.path_folder_dpt, self.folder_processing, self.captor_project)
 
 		dossier_rpg = "{0}/RPG".format(self.folder_processing)
-		
+
 		# Extract rpg crops
 		mono_sample = Rpg(path_rpg, self.path_area)
-		
+
 		mono_sample.clip_vector(dossier_rpg)
 		mono_sample.vector_data()
 
@@ -440,25 +439,25 @@ class Processing(object):
 		mono_sample.logger.close()
 
 		return mono_sample.vector_used
-		 
+
 	def i_sample(self):
 		"""
-			Interface function to compute threshold with various sample. 
-			It also extract a list of validation layer (shapefile) 
-			to compute the precision of the next classification : func:`i_validate`. 
-			
-			It create samples 2 by 2 with kwargs field names and class :func:`Sample.Sample.create_sample`. 
+			Interface function to compute threshold with various sample.
+			It also extract a list of validation layer (shapefile)
+			to compute the precision of the next classification : func:`i_validate`.
+
+			It create samples 2 by 2 with kwargs field names and class :func:`Sample.Sample.create_sample`.
 			Then, it compute zonal statistics by polygons :func:`Vector.Sample.zonal_stats`.
-			
+
 			With zonal statistics computed, a optimal threshold is determined :
-			 func:`Seath.Seath.separability_and_threshold` that will print in a text file .lg 
+			 func:`Seath.Seath.separability_and_threshold` that will print in a text file .lg
 			 in the main folder.
-			
+
 			.. warning:: :func:`Seath.Seath.separability_and_threshold` does not always
 			 allow to discriminate optimal threshold. Then, this function will be launch
 			 at least ten time until it reaches a optimal threshold.
 		"""
-		
+
 		# Compute threshold with various sample
 		i_s = 0
 		while i_s < 10:
@@ -483,24 +482,24 @@ class Processing(object):
 					sample_rd[sple].create_sample(**kwargs)
 					sample_rd[sple].zonal_stats((self.raster_path[round(sple/2)],\
 					 self.list_band_outraster[round(sple/2)]))
-					
+
 					# Add the validation shapefile
 					self.valid_shp.append([sample_rd[sple].vector_val, kwargs['fieldname'], kwargs['class']])
-				
-				# Search the optimal threshold by class 
+
+				# Search the optimal threshold by class
 				# Open a text file to print stats of Seath method
-				with open("{0}/log_J.lg".format(self.path_folder_dpt), "wb") as f : 
+				with open("{0}/log_J.lg".format(self.path_folder_dpt), "wb") as f :
 					for th_seath in range(len(self.sample_name)):
 						self.decis[th_seath] = Seath()
 						self.decis[th_seath].value_1 = sample_rd[th_seath*2].stats_dict
 						self.decis[th_seath].value_2 = sample_rd[th_seath*2 + 1].stats_dict
 						self.decis[th_seath].separability_and_threshold()
-						
+
 						# Print the J value in the text file .lg
 						f.write('For {0} :\n'.format(self.sample_name[th_seath]))
 						f.write('J = {0}\n'.format(self.decis[th_seath].J[0]))
 						f.write('The class 1 {0}\n'.format(self.decis[th_seath].threshold[0]))
-	
+
 				i_s = 20
 			except Exception as e:
 				self.logger.error("Error 519 : {0}".format(e))
@@ -510,17 +509,16 @@ class Processing(object):
 		if i_s != 20 or True:
 			self.logger.error('Problem during the sample processing.')
 			sys.exit(1)
-	
+
 	def i_sample_rf(self):
 		"""
 			This function build a random forest trees like model to create a final classification.
 			All of this using the method described in the : func:`i_validate` function and because
 			of sklearn module.
 		"""
-		
+
 		X_rf = []
 		y_rf = []
-		sample_rd = {}	
 
 		self.liste_chemin = [self.out_ndvistats_folder_tab['Min'], self.out_ndvistats_folder_tab['sfs'],\
 			self.out_ndvistats_folder_tab['haralick'], self.out_ndvistats_folder_tab['Max'] ]
@@ -534,32 +532,32 @@ class Processing(object):
 			self.logger.debug("Creation Sample : {0} - {1} - {2}".format(\
 				self.sample_name[round(sple/2)], self.path_area, self.list_nb_sample[round(sple/2)]) )
 
-			sample_rd[sple] = Sample(self.sample_name[round(sple/2)], self.path_area,\
+			sample_rd = Sample(self.sample_name[round(sple/2)], self.path_area,\
 			 self.list_nb_sample[round(sple/2)])
 
-			sample_rd[sple].clip_vector("{0}/{1}".format(self.folder_processing, os.path.basename(\
+			sample_rd.clip_vector("{0}/{1}".format(self.folder_processing, os.path.basename(\
 				os.path.dirname(self.sample_name[round(sple/2)]))))
-			
-			sample_rd[sple].vector_data()
-			sample_rd[sple].output_folder = self.folder_processing
-		
+
+			sample_rd.vector_data()
+			sample_rd.output_folder = self.folder_processing
+
 			self.logger.debug("kwargs : {0}".format(kwargs))
 
-			sample_rd[sple].create_sample(**kwargs)
+			sample_rd.create_sample(**kwargs)
 
 			# Add the validation shapefile
-			self.valid_shp.append([sample_rd[sple].vector_val, kwargs['fieldname'], kwargs['class']])
+			self.valid_shp.append([sample_rd.vector_val, kwargs['fieldname'], kwargs['class']])
 
 			items = list(self.raster_path.items())
 
 			self.logger.debug("Raster path items: {0}".format(self.raster_path.items()))
 
-			sample_rd[sple].zonal_stats(self.liste_chemin)
+			sample_rd.zonal_stats(self.liste_chemin)
 
 			# To convert the dictionnary in a list
-			for key, value in sample_rd[sple].stats_dict.items():
+			for key, value in sample_rd.stats_dict.items():
 				# X_rf.append([-10000 if (math.isnan(x) or math.isinf(x)) else x for x in value])
-				# To set the grassland class of the RPG and PIAO (same class)			
+				# To set the grassland class of the RPG and PIAO (same class)
 				if sple == 2 :
 					# y_rf.append(1)
 					pass
@@ -568,53 +566,61 @@ class Processing(object):
 					pass
 				else :
 					y_rf.append(sple)
-					X_rf.append([-10000 if (x is None or math.isnan(x) or math.isinf(x)) else x for x in value])
-		
-			sample_rd[sple].logger.close()
+					# X_rf.append([-10000 if (x is None or math.isnan(x) or math.isinf(x)) else x for x in value])
+					X_rf.append([x for x in value if (x is not None and not math.isnan(x) and not math.isinf(x))])
+
+			sample_rd.logger.close()
+			sample_rd = None
 
-		# Build a forest of trees from the samples				 
+		# Build a forest of trees from the samples
 		self.rf = self.rf.fit(X_rf, y_rf)
-		
+
+		X_rf = None
+		y_rf = None
+
 		# Print in a file feature important
 		importance = self.rf.feature_importances_
 		importance = [(importance[x],x+1) for x in range(len(importance))]
 		importance.sort()
-		
+
 		file_feat_import = "{0}/Feature_important_RF.ft".format(self.folder_processing)
 
 		if os.path.exists(file_feat_import):
 			os.remove(file_feat_import)
-		
+
 		with open(file_feat_import, "w") as f_out :
 			f_out.write("{0}".format(importance))
-		
+
 		# Print in a file decision tree
 		file_decisiontree = "{0}/Decision_tree.dot".format(self.folder_processing)
-		
+		image_decisiontree = "{0}/Decision_tree.png".format(self.folder_processing)
+
 		if os.path.exists(file_decisiontree):
 			os.remove(file_decisiontree)
-		
+
 		tree_in_forest = self.rf.estimators_[499]
 
 		with open(file_decisiontree, 'w') as my_file:
 			my_file = tree.export_graphviz(tree_in_forest, out_file = my_file)
 
-	def i_classifier_rf(self): 
+		(graph,) = pydot.graph_from_dot_file(file_decisiontree)
+		graph.write_png(image_decisiontree)
+
+	def i_classifier_rf(self):
 		"""
-			Interface function to launch random forest classification with a input segmentation : 
+			Interface function to launch random forest classification with a input segmentation :
 			 func:`Segmentation.Segmentation`.
-		
+
 			This function use the sklearn module to build the best of decision tree to extract classes.
 			The optimal threshold are stored by class **rf** variable in :func:`Processing.i_sample_rf`.
 			Then it computes zonal statistics by polygons for every images in multi-processing (if **mp** = 1).
 		"""
-		
+
 		# Multiprocessing
 		mgr = BaseManager()
 		mgr.register('defaultdict', defaultdict, DictProxy)
 		mgr.start()
-		multi_process_var = [] # Multi processing variable
-		  
+
 		# Extract final cartography
 		out_carto = Segmentation.Segmentation(self.path_segm, self.path_area)
 
@@ -633,7 +639,7 @@ class Processing(object):
 
 		# Stats backup file
 		file_stats = "{0}/Stats_raster_spectral_texture.stats".format(self.folder_processing)
-			
+
 		p = []
 		kwargs = {}
 		X_out_rf = [] # Variable list to compute decision tree with random forest method
@@ -644,13 +650,15 @@ class Processing(object):
 				out_carto.stats_dict = mgr.defaultdict(list)
 
 				out_carto.zonal_stats(self.liste_chemin)
-									
+
 				for key, value_seg in out_carto.stats_dict.items():
-					true_value = [-10000 if (x is None or math.isnan(x) or math.isinf(x)) else x for x in value_seg]
+					# true_value = [-10000 if (x is None or math.isnan(x) or math.isinf(x)) else x for x in value_seg]
+					true_value = [x for x in value_seg if (x is not None and not math.isnan(x) and not math.isinf(x))]
+
 					X_out_rf.append(true_value)
-					
+
 					f_out.write("{0}\n".format(true_value))
-		
+
 		else:
 			# If the stats file exists already, open this file and append in the stats_dict variable
 			out_carto.stats_dict = defaultdict(list)
@@ -662,19 +670,20 @@ class Processing(object):
 					X_out_rf.append(eval(x_in.strip('\n')))
 
 		predicted_rf = self.rf.predict(X_out_rf)
+		X_out_rf = None
 
 		self.logger.debug("Taille sample_name : {0}".format(len(self.sample_name)))
-			 
+
 		# For the higher than level 1
 		if len(self.sample_name) > 2:
 			# Compute the biomass and density distribution
 			# Use 'out_carto.out_threshold' to know predicted in the segmentation class
 			out_carto.out_threshold["PREDICTION"] = predicted_rf
-			
-			# In the compute_biomass_density function, this variable used normally to define 
+
+			# In the compute_biomass_density function, this variable used normally to define
 			# threshold of the classification with SEATH method is initialized
 			out_carto.compute_biomass_density('RF')
-		
+
 		out_carto.class_tab_final = defaultdict(list)
 		for i_polyg in range(len(predicted_rf)):
 			i_final = 0
@@ -686,24 +695,27 @@ class Processing(object):
 					class_final = self.tree_direction[i_final]
 					i_final = len(self.tree_direction)
 				i_final = i_final + 1
-			
+
 			if class_final == []:
 				class_final = [1, 2]
-			# Set the class name because of predicted output formatted		 
+			# Set the class name because of predicted output formatted
 			out_carto.class_tab_final[i_polyg] = [self.in_class_name[f] for f in class_final] + \
 												[predicted_rf[i_polyg]] + [predicted_rf[i_polyg]]
-			
+
 			# For the output line with one level, add a phantom level
 			# TODO : Replace constant by a variable in the condition 'while'
 			while len(out_carto.class_tab_final[i_polyg]) < 5:
 				out_carto.class_tab_final[i_polyg].insert(len(out_carto.class_tab_final[i_polyg])-2,'')
-		
+
+		predicted_rf = None
 		# If there is more one fieldnames line edit fulled in classification tab
 		if len(self.sample_name) > 2:
 			# Compute biomass and density scale
 			out_carto.append_scale(self.in_class_name[2], 'self.stats_dict[ind_stats][3]/self.max_bio')
 			out_carto.append_scale(self.in_class_name[3], 'self.stats_dict[ind_stats][2]/self.max_wood_idm')
-		
+
+		out_carto.stats_dict = None
+
 		# Rasterize RPG shapefile to complete the final shapefile
 		opt = {}
 		opt['Remove'] = 1
@@ -712,32 +724,33 @@ class Processing(object):
 		rpg_tif.clip_vector(os.path.dirname(self.sample_name[0]))
 		rpg_tif.vector_data()
 
-		self.logger.debug(self.path_ortho)
+		self.logger.debug("path_ortho : {0}".format(self.path_ortho))
 		out_carto.stats_rpg_tif = out_carto.zonal_stats_pp(rpg_tif.layer_rasterization(self.path_ortho, 'CODE_GROUP'))
 
 		# Final cartography
 		out_carto.create_cartography(self.out_fieldname_carto, self.out_fieldtype_carto)
-		
-	def i_classifier_s(self): 
+		out_carto = None
+
+	def i_classifier_s(self):
 		"""
-		Interface function to launch decision tree classification with a input 
+		Interface function to launch decision tree classification with a input
 		segmentation :func:`Segmentation.Segmentation`.
-		
+
 		This function store optimal threshold by class **Segmentation.out_threshold**.
 		Then it computes zonal statistics by polygons for every images in multi-processing (if **mp** = 1).
-		""" 
-		
+		"""
+
 		# Multiprocessing
 		mgr = BaseManager()
 		mgr.register('defaultdict', defaultdict, DictProxy)
 		mgr.start()
 		multi_process_var = [] # Multi processing variable
-		  
+
 		# Extract final cartography
-		out_carto = Segmentation(self.path_segm, self.path_area) 
+		out_carto = Segmentation(self.path_segm, self.path_area)
 		out_carto.output_file = self.output_name_moba
 		out_carto.out_class_name = self.in_class_name
-		
+
 		for ind_th in range(len(self.sample_name)):
 			out_carto.out_threshold.append(self.decis[ind_th].threshold[0])
 			if '>' in self.decis[ind_th].threshold[0]:
@@ -747,7 +760,7 @@ class Processing(object):
 			# out_carto.zonal_stats((raster_path[ind_th], list_band_outraster[ind_th]))
 
 			multi_process_var.append([self.raster_path[ind_th], self.list_band_outraster[ind_th]])
-		 
+
 		# Compute zonal stats on slope raster
 		multi_process_var.append([self.raster_path[ind_th+1], self.list_band_outraster[ind_th+1]])
 		out_carto.out_threshold.append('<'+str(self.slope_degree)) # To agriculture
@@ -756,8 +769,8 @@ class Processing(object):
 			# Add class indexes
 			self.tree_direction[0].append(6)
 			self.tree_direction[0].append(7)
-			
-		# Compute zonal stats on Max NDVI raster  
+
+		# Compute zonal stats on Max NDVI raster
 		try:
 			# out_carto.zonal_stats((raster_path[ind_th+1], list_band_outraster[ind_th+1]))
 			multi_process_var.append([self.raster_path[ind_th+2], self.list_band_outraster[ind_th+2]])
@@ -776,7 +789,7 @@ class Processing(object):
 			exist_stats = 0 # The sats file doesn't exist
 			# Open a stats backup to avoid computing again (Gain of time)
 			f_out = open(file_stats, "wb")
-			
+
 		p = []
 		kwargs = {}
 		X_out_rf = [] # Variable list to compute decision tree with random forest method
@@ -787,23 +800,24 @@ class Processing(object):
 				kwargs['nb_img'] = len(multi_process_var)
 				p.append(Process(target=out_carto.zonal_stats, args=(multi_process_var[i], ), kwargs=kwargs))
 				p[i].start()
-				
+
 				if self.mp == Constantes.MULTIPROCESSING_DISABLE:
 					p[i].join()
-			
-			if self.mp == Constantes.MULTIPROCESSING_ENABLE:	   
+
+			if self.mp == Constantes.MULTIPROCESSING_ENABLE:
 				for i in range(len(multi_process_var)):
 					p[i].join()
-					
+
 			for key, value_seg in out_carto.stats_dict.items():
-				
-				true_value = [-10000 if (math.isnan(x) or math.isinf(x)) else x for x in value_seg]
+
+				# true_value = [-10000 if (math.isnan(x) or math.isinf(x)) else x for x in value_seg]
+				true_value = [x for x in value_seg if (not math.isnan(x) and not math.isinf(x))]
 				# Print rasters stats value in the text file .lg
 				f_out.write(str(true_value) + '\n')
-			
+
 			# Close the output file
 			f_out.close()
-			
+
 		else:
 			# If the stats file exists already, open this file and append in the stats_dict variable
 			out_carto.stats_dict = defaultdict(list)
@@ -813,36 +827,36 @@ class Processing(object):
 					index_in_stats = index_in_stats + 1
 					out_carto.stats_dict[index_in_stats] = eval(x_in.strip('\n'))
 					X_out_rf.append(eval(x_in.strip('\n')))
-		
-		# For the higher than level 1 
+
+		# For the higher than level 1
 		if len(self.sample_name) > 2:
 			# Compute the biomass and density distribution
 			out_carto.compute_biomass_density()
-			
+
 		out_carto.class_tab_final = defaultdict(list)
 		self.i_tree_direction()
 		out_carto.decision_tree(self.tree_direction)
-		
+
 		# If there is more one fieldnames line edit fulled in classification tab
-		if len(self.sample_name) > 2:	 
+		if len(self.sample_name) > 2:
 			# Compute biomass and density scale
 			out_carto.append_scale(self.in_class_name[2], 'self.stats_dict[ind_stats][3]/self.max_bio')
 			out_carto.append_scale(self.in_class_name[3], 'self.stats_dict[ind_stats][2]/self.max_wood_idm')
-		
+
 		# Rasterize RPG shapefile to complete the final shapefile
 		opt = {}
 		opt['Remove'] = 1
 		rpg_tif = Vector(self.sample_name[0], self.path_area, **opt)
 		rpg_tif.layer_rasterization(self.path_ortho, 'CODE_GROUP')
-		  
+
 		# Final cartography
 		out_carto.mono_rpg_tif = "{0}.TIF".format(self.sample_name[0][:-4])
 		out_carto.create_cartography(self.out_fieldname_carto, self.out_fieldtype_carto)
-	   
+
 	def i_validate(self):
 		"""
-			Interface to validate a classification. It going to rasterize the validation shapefile and the 
-			classification shapefile with :func:`layer_rasterization`. 
+			Interface to validate a classification. It going to rasterize the validation shapefile and the
+			classification shapefile with :func:`layer_rasterization`.
 			Next, to compare pixel by pixel, the classification quality to built a confusion matrix in a csv file.
 		"""
 
@@ -855,10 +869,10 @@ class Processing(object):
 		complete_validate_shp = "{0}/validate.shp".format(os.path.dirname(self.valid_shp[0][0]))
 
 		# TODO: Set this method in the Precision_moba class
-		
+
 		# Processing to rasterize the validate shapefile. 1) Merge sahpefiles 2) Rasterization
 		for val in self.valid_shp:
-			if class_validate != 2: 
+			if class_validate != 2:
 				# Grassland to 1
 				if (class_validate !=3 and len(self.out_fieldname_carto) != 4+2) or len(self.out_fieldname_carto) == 4+2:
 					# To the level 3 with woodeen to 4 and 5
@@ -866,15 +880,15 @@ class Processing(object):
 					# Self.valid_shp is a list of list. In this variable there is :
 					# [Shapefile path, fieldname classes, classnames]
 					opt = {}
-					opt['Remove'] = 1 # To overwrite 
-		
+					opt['Remove'] = 1 # To overwrite
+
 					# Create a raster to valide the classification
 					# First time, create a new shapefile with a new field integer
 					sample_val = Sample(val[0], self.path_area, 1, **opt)
-					opt['add_fieldname'] = 1 
+					opt['add_fieldname'] = 1
 					opt['fieldname'] = 'CLASS_CODE'
 					opt['class'] = str(class_validate) # Add integer classes
-					
+
 					# Set the new shapefile
 					val[0] = "{0}_.shp".format(val[0][:-4])
 					val[1] = opt['fieldname']
@@ -882,36 +896,36 @@ class Processing(object):
 
 					sample_val.clip_vector(sample_val.vector_folder)
 					sample_val.vector_data()
-					
+
 					# Complete the new shapefile
 					sample_val.fill_sample(val[0], 0, **opt)
-					
+
 					# Second time, merge the validate shapefile
 					if class_validate == 0 :
 						process_tocall_merge = ['ogr2ogr', '-overwrite', complete_validate_shp, val[0]]
 					elif class_validate > 0 :
 						process_tocall_merge = ['ogr2ogr', '-update', '-append', complete_validate_shp, \
 										val[0], '-nln', os.path.basename(str(complete_validate_shp[:-4]))]
-					
+
 					subprocess.call(process_tocall_merge)
 
 					sample_val.logger.close()
-			
-			# Increrment variable
+
+			# Increment variable
 			class_validate = self.valid_shp.index(val) + 1
-		
+
 		# Compute precision of the classification
-		valid = Precision_moba(self.path_area, self.path_folder_dpt)	 
+		valid = Precision_moba(self.path_area, self.path_folder_dpt)
 		valid.complete_validation_shp = complete_validate_shp
 
 		valid.ex_raster = list(self.raster_path.items())[0][1]["PATH"]
 
 		# TODO: Call the RasterSat_by_Date class here instead of the Precision_moba class
 		self.logger.debug("Name moba : {0}".format(self.output_name_moba))
-		
+
 		valid.preprocess_to_raster_precision(self.output_name_moba, 'FBPHY_CODE') # To the classification's data
 		valid.preprocess_to_raster_precision(complete_validate_shp, val[1]) # To the validation's data
-		
+
 		# Compute precision on the output classification
 		valid.confus_matrix(valid.complete_img[0].raster_data(valid.img_pr[0])[0], valid.complete_img[1].raster_data(valid.img_pr[1])[0])
 
diff --git a/Sample.py b/Sample.py
index 266127d..0c2ce2b 100644
--- a/Sample.py
+++ b/Sample.py
@@ -3,17 +3,17 @@
 #
 # This file is part of PHYMOBAT 1.2.
 # Copyright 2016 Sylvio Laventure (IRSTEA - UMR TETIS)
-# 
+#
 # PHYMOBAT 1.2 is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation, either version 3 of the License, or
 # (at your option) any later version.
-# 
+#
 # PHYMOBAT 1.2 is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License
 # along with PHYMOBAT 1.2.  If not, see <http://www.gnu.org/licenses/>.
 
@@ -31,9 +31,9 @@ except :
 
 class Sample(Vector):
 	"""
-		Vector class inherits the super vector class properties. 
+		Vector class inherits the super vector class properties.
 		This class create training sample.
-	
+
 		@param vector_used: Input/Output shapefile to clip (path)
 		@type vector_used: str
 
@@ -45,32 +45,32 @@ class Sample(Vector):
 
 		@param vector_val: Output shapefile to validate the futur classification
 		@type vector_val: str
-	
+
 		@opt: Refer to the Vector class
 	"""
-	
+
 	def __init__(self, used, cut, nb_sample, **opt):
 		"""
-			Create a new 'Sample' instance   
+			Create a new 'Sample' instance
 		"""
 
 		self.logger = Outils.Log('Log', 'Sample')
-		
+
 		Vector.__init__(self, used, cut, **opt)
-		
+
 		self._nb_sample = nb_sample
 		self.vector_val = ''
-	
+
 	def create_sample(self, **kwargs):
 		"""
 			Function to create a sample shapefile of a specific class
-		
+
 			:kwargs: **fieldname** (list of str) - Fieldname in the input shapefile (if the user want select polygons of the class names specific)
-				
+
 			**class** (list of str) - class names in the input shapefile (with fieldname index).
 			Can use one or several classes like this --> example : [classname1, classname2, ...]
 		"""
-		
+
 		kw_field = kwargs['fieldname'] if kwargs.get('fieldname') else ''
 		kw_classes = kwargs['class'] if kwargs.get('class') else ''
 
@@ -78,7 +78,7 @@ class Sample(Vector):
 		self.logger.debug("kw_classes : {0}".format(kw_classes))
 
 		self.output_folder = "{0}/{1}".format(self.output_folder, os.path.basename(os.path.dirname(self.vector_used)))
-		
+
 		if not os.path.exists(self.output_folder) :
 			os.mkdir(self.output_folder)
 
@@ -89,7 +89,7 @@ class Sample(Vector):
 		else:
 			# The random sample without class name selected
 			random_sample = np.array(random.sample(range(self.data_source.GetLayer().GetFeatureCount()), self._nb_sample))
-			
+
 		self.logger.debug("random_sample : {0}".format(random_sample))
 
 		# Output shapefile of the sample's polygons (path)
@@ -102,61 +102,51 @@ class Sample(Vector):
 
 		# Fill and create the sample shapefile
 		self.fill_sample(self.vector_used, random_sample[:round(len(random_sample)/2)])
-	
+
 		# Output shapefile of the validate polygon (path)
-		self.vector_val = "{0}val.shp".format(self.vector_used[:-6]) 
-		
+		self.vector_val = "{0}val.shp".format(self.vector_used[:-6])
+
 		# Fill and create the validate polygons shapefile
 		self.fill_sample(self.vector_val, random_sample[round(len(random_sample)/2):])
 
-	def select_random_sample(self, kw_field, kw_classes):		
+	def select_random_sample(self, kw_field, kw_classes):
 		"""
 			Function to select id with class name specific only.
-			 This function is used in :func:`create_sample`
+			This function is used in :func:`create_sample`
 
 			@param kw_field: Field name in the input shapefile
 			@type kw_field: str
-			
+
 			@param kw_classes: Class names in the input shapefile like this --> 'classname1, classname2'
 			@type kw_classes: str
-			
+
 			@returns: list -- variable **select_id**, List of id with a class name specific.
 		"""
-		
+
 		# Convert string in a list. For that, it remove
 		# space and clip this string with comma (Add everywhere if the script modified
 		# because the process work with a input string chain)
-
 		kw_classes = kw_classes.replace(' ','').split(',')
-		self.logger.debug('kw_classes : {0}'.format(kw_classes))
-		
+
 		# List of class name id
 		select_id = []
 
-		shp_ogr = self.data_source.GetLayer()
+		layer = self.data_source.GetLayer()
 
-		# Loop on input polygons
-		in_feature = shp_ogr.SetNextByIndex(0) # Initialization
-		in_feature = shp_ogr.GetNextFeature()
-		
-		while in_feature:			
-			# if polygon is a defined class name 
-			## .replace('0','') to remove '0' in front of for example '1' (RPG -> '01')
-			table_name_class = in_feature.GetField(self.field_names[self.field_names.index(kw_field)])
-			# To avoid that the process crashed this part of the algorithm will be launch
-			# if the field is contains characters
-			if table_name_class != None :
-				if in_feature.GetField(self.field_names[self.field_names.index(kw_field)]).replace('0','') in kw_classes:
-					
-					# Add id in the extract list
-					select_id.append(in_feature.GetFID())
-	
-					in_feature.Destroy()
-					   
-			in_feature = shp_ogr.GetNextFeature()
+		assert layer.GetFeatureCount() != 0, "Le shapefile : {0} est vide.".format(self.data_source.GetLayer().GetName())
+
+		for i in range(layer.GetFeatureCount()) :
+			feature = layer.GetFeature(i)
+
+			if feature.GetFieldIndex(self.field_names[self.field_names.index(kw_field)]) != -1 \
+			and not feature.GetField(self.field_names[self.field_names.index(kw_field)]) is None :
+				if feature.GetField(self.field_names[self.field_names.index(kw_field)]).replace('0','') in kw_classes :
+					select_id.append(i)
+
+		assert len(select_id) > 0, "Aucun polygone ne correspond."
 
 		return select_id
-	
+
 	def fill_sample(self, output_sample, polygon, **opt):
 		"""
 			Function to fill and create the output sample shapefile.
@@ -165,15 +155,15 @@ class Sample(Vector):
 
 			@param output_sample: Path of the output shapefile
 			@type output_sample: str
-			
+
 			@param polygon: Identity of the selected random polygons.
-			 If this variable = 0, the processing will take all polygons 
-			@type polygon: list or int	  
-		
+			 If this variable = 0, the processing will take all polygons
+			@type polygon: list or int
+
 			@opt: **add_fieldname** (int) - Variable to kown if add a field. By default non (0), if it have to add (1)
-		
+
 					**fieldname** (str) - Fieldname to add in the input shapefile
-				
+
 					**class** (int) - class names in integer to add in the input shapefile
 		"""
 
@@ -181,56 +171,56 @@ class Sample(Vector):
 		add_field = opt['add_fieldname'] if opt.get('add_fieldname') else 0
 		opt_field = opt['fieldname'] if opt.get('fieldname') else ''
 		opt_class = opt['class'] if opt.get('class') else 0
-		
+
 		shp_ogr = self.data_source.GetLayer()
-		
+
 		# To take all polygon
 		if type(polygon) == int:
 			polygon = range(shp_ogr.GetFeatureCount())
-		
+
 		# Projection
 		# Import input shapefile projection
 		srsObj = shp_ogr.GetSpatialRef()
 		# Conversion to syntax ESRI
-		srsObj.MorphToESRI() 
-			   
+		srsObj.MorphToESRI()
+
 		## Remove the output shapefile if it exists
 		if os.path.exists(output_sample):
 			self.data_source.GetDriver().DeleteDataSource(output_sample)
-			
+
 		out_ds = self.data_source.GetDriver().CreateDataSource(output_sample)
-		
+
 		if out_ds is None:
 			self.logger.error('Could not create file')
 			sys.exit(1)
-			
+
 		#  Specific output layer
 		out_layer = out_ds.CreateLayer(output_sample, srsObj, geom_type=ogr.wkbMultiPolygon)
-		
-		# Add existing fields 
+
+		# Add existing fields
 		for i in range(0, len(self.field_names)):
 			# use the input FieldDefn to add a field to the output
 			fieldDefn = shp_ogr.GetFeature(0).GetFieldDefnRef(self.field_names[i])
 			out_layer.CreateField(fieldDefn)
-			
+
 		# In Option : Add a integer field
 		if add_field == 1:
 			new_field = ogr.FieldDefn(opt_field, 0)
 			out_layer.CreateField(new_field)
-		
+
 		# Feature for the ouput shapefile
 		featureDefn = out_layer.GetLayerDefn()
-		
+
 		# Loop on the input elements
-		# Create a existing polygons in random list	
+		# Create a existing polygons in random list
 		for cnt in polygon:
-			
+
 			# Select input polygon by id
 			in_feature = shp_ogr.SetNextByIndex(cnt)
 			in_feature = shp_ogr.GetNextFeature()
-			
+
 			# Extract input geometry
-			geom = in_feature.GetGeometryRef() 
+			geom = in_feature.GetGeometryRef()
 
 			# Create a new polygon
 			out_feature = ogr.Feature(featureDefn)
@@ -249,10 +239,10 @@ class Sample(Vector):
 
 			# Append polygon to the output shapefile
 			out_layer.CreateFeature(out_feature)
-	
+
 			# Destroy polygons
-			out_feature.Destroy()	
+			out_feature.Destroy()
 			in_feature.Destroy()
-			
+
 		# Close data
-		out_ds.Destroy()		
\ No newline at end of file
+		out_ds.Destroy()
diff --git a/Vector.py b/Vector.py
index e9fd31c..2cca534 100644
--- a/Vector.py
+++ b/Vector.py
@@ -3,39 +3,34 @@
 #
 # This file is part of PHYMOBAT 1.2.
 # Copyright 2016 Sylvio Laventure (IRSTEA - UMR TETIS)
-# 
+#
 # PHYMOBAT 1.2 is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation, either version 3 of the License, or
 # (at your option) any later version.
-# 
+#
 # PHYMOBAT 1.2 is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License
 # along with PHYMOBAT 1.2.  If not, see <http://www.gnu.org/licenses/>.
 
 import os, sys
 import subprocess
 import numpy as np
-import osgeo
-
-# try :
-# 	import ogr, gdal
-# except :
-# 	from osgeo import ogr, gdal
-	
+from osgeo import ogr
 import otbApplication as otb
 from collections import *
+
 import Outils
 from RasterSat_by_date import RasterSat_by_date
 
 class Vector():
-	"""	
+	"""
 		Vector class to extract a area, vector data and zonal statistic
-		
+
 		@param vector_used: Input/Output shapefile to clip (path)
 		@type vector_used: str
 
@@ -59,10 +54,10 @@ class Vector():
 
 		@opt: **Remove** (int) - For the remove_shp variable
 	"""
-	  
+
 	def __init__(self, used, cut, **opt):
 		"""
-			Create a new 'Vector' instance   
+			Create a new 'Vector' instance
 		"""
 
 		if not hasattr(self, "logger") :
@@ -74,19 +69,19 @@ class Vector():
 		self.vector_cut = cut
 		self.vector_used = used
 		self.remove_shp = opt['Remove'] if opt.get('Remove') else 0
-	
+
 		self.stats_dict = defaultdict(list)
-	
+
 	def clip_vector(self, output_folder):
 		"""
 			Function to clip a vector with a vector
-		"""	
+		"""
 
 		if not os.path.exists(output_folder) :
 			os.makedirs(output_folder)
-		
+
 		outclip = "{0}/Clip_{1}".format(output_folder, self.vector_name)
-		
+
 		if not os.path.exists(outclip) or self.remove_shp == 1:
 			self.logger.info('Clip of {0}'.format(self.vector_name))
 
@@ -100,43 +95,43 @@ class Vector():
 
 		# Replace input filename by output filename
 		self.vector_used = outclip
-		
+
 	def vector_data(self):
 		"""
-			Function to extract vector layer information 
+			Function to extract vector layer information
 		"""
 
 		try:
-			self.data_source = osgeo.ogr.GetDriverByName('ESRI Shapefile').Open(self.vector_used, 0)
+			self.data_source = ogr.Open(self.vector_used)
 			self.logger.info('Shapefile opening : {0}'.format(self.data_source.GetLayer().GetName()))
 		except :
 			self.logger.error('Could not open file')
-			sys.exit(1)	
+			sys.exit(1)
 
 		# List of field name
 		self.field_names = [self.data_source.GetLayer().GetLayerDefn().GetFieldDefn(l).GetName() \
-						for l in range(self.data_source.GetLayer().GetLayerDefn().GetFieldCount())]	
+						for l in range(self.data_source.GetLayer().GetLayerDefn().GetFieldCount())]
 
 	def close_data(self):
 		"""
-			Function to remove allocate memory			
-		"""		
-		
+			Function to remove allocate memory
+		"""
+
+		self.logger.info('Shapefile closing : {0}'.format(self.data_source.GetLayer().GetName()))
+
 		# Close data sources
 		self.data_source.Destroy()
-		
-		self.logger.info('Shapefile closing : {0}'.format(self.data_source.GetLayer().GetName()))
-	
+
 	def zonal_stats(self, liste_chemin):
 		"""
 			Function to compute the mean in every polygons on a list images with otb
-			
-			:param liste_chemin : List input image path
-			:type liste_chemin: list(string)
+
+			@param liste_chemin : List input image path
+			@type  liste_chemin : list(string)
 		"""
-		
+
 		self.logger.info("Compute stats 'mean' on {0}".format(os.path.split(self.vector_used)[1]))
-		
+
 		zonal_stats = otb.Registry.CreateApplication("ZonalStatistics")
 		zonal_stats.SetParameterStringList("il", liste_chemin)
 		zonal_stats.SetParameterStringList("vec", [self.vector_used])
@@ -159,15 +154,15 @@ class Vector():
 
 		for idx, r in enumerate(resultats) :
 			self.stats_dict[idx] = r.tolist()
-					
+
 		self.logger.info("End of stats 'mean' on {0}".format(os.path.split(self.vector_used)[1]))
 
 	def zonal_stats_pp(self, inraster):
 		"""
 			A zonal statistics ++ to dertermine pxl percent in every polygon
-		
+
 			:param inraster: Input image path
-			:type inraster: str 
+			:type inraster: str
 
 			:returns: dict -- **p_stats** : dictionnary with pxl percent in every polygon. Mainly 'Maj_count' (Majority Value) and 'Maj_count_perc' (Majority Percent)
 		"""
@@ -191,30 +186,30 @@ class Vector():
 			dico['Maj_count'] = float(liste_item[1])
 			dico['Maj_count_perc'] = float(liste_item[2])
 			p_stats.append(dico)
-		
+
 		return p_stats
-				
+
 	def layer_rasterization(self, raster_head, attribute_r, **kwargs):
 		"""
 			Function to rasterize a vector using OTB.
-			
+
 			@param raster_head: Raster path that will look like the final raster of the rasterization
 			@type raster_head: str
 
 			@param attribute_r: Field name of the shapefile that contains class names
 			@type attribute_r: str
 
-			@kwargs: **choice_nb_b** (int) - Output image number of band. If you choice 1, take first band. If you choice 2, take two first band etc... 
+			@kwargs: **choice_nb_b** (int) - Output image number of band. If you choice 1, take first band. If you choice 2, take two first band etc...
 			@returns: str -- **valid_raster** : output raster path from the rasterization
 		"""
 
 		valid_raster = "{0}.TIF".format(self.vector_used[:-4])# Name of the output raster
 
 		self.logger.debug("valid_raster : {0}".format(valid_raster))
-		
+
 		if os.path.exists(valid_raster):
 			os.remove(valid_raster)
-		
+
 		layerRasterization = otb.Registry.CreateApplication("Rasterization")
 		layerRasterization.SetParameterString("in", self.vector_used)
 		layerRasterization.SetParameterString("out", valid_raster)
@@ -223,5 +218,5 @@ class Vector():
 		layerRasterization.SetParameterString("mode.attribute.field", attribute_r)
 
 		layerRasterization.ExecuteAndWriteOutput()
-		
-		return valid_raster
\ No newline at end of file
+
+		return valid_raster
-- 
GitLab