Commit f66dc771 authored by Commandre Benjamin's avatar Commandre Benjamin
Browse files

Nettoyage

1 merge request!1Develop
Showing with 55 additions and 62 deletions
+55 -62
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# This file is part of PHYMOBAT 1.2. # This file is part of PHYMOBAT 1.2.
# Copyright 2016 Sylvio Laventure (IRSTEA - UMR TETIS) # Copyright 2016 Sylvio Laventure (IRSTEA - UMR TETIS)
# #
# PHYMOBAT 1.2 is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# PHYMOBAT 1.2 is distributed in the hope that it will be useful, # PHYMOBAT 1.2 is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # 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/>. # along with PHYMOBAT 1.2. If not, see <http://www.gnu.org/licenses/>.
...@@ -31,9 +31,9 @@ from collections import * ...@@ -31,9 +31,9 @@ from collections import *
class Segmentation(Vector): class Segmentation(Vector):
""" """
Vector class inherits the super vector class properties. This class create the final shapefile : Cartography Vector class inherits the super vector class properties. This class create the final shapefile : Cartography
on a input segmentation by decision tree. on a input segmentation by decision tree.
The output classname are (**out_class_name** variable): The output classname are (**out_class_name** variable):
- Vegetation non naturelle - Vegetation non naturelle
- Vegetation semi-naturelle - Vegetation semi-naturelle
...@@ -44,7 +44,7 @@ class Segmentation(Vector): ...@@ -44,7 +44,7 @@ class Segmentation(Vector):
- Forte phytomasse - Forte phytomasse
- Moyenne phytomasse - Moyenne phytomasse
- Faible phytomasse - Faible phytomasse
@param vector_used: Input/Output shapefile to clip (path) @param vector_used: Input/Output shapefile to clip (path)
@type vector_used: str @type vector_used: str
...@@ -70,7 +70,7 @@ class Segmentation(Vector): ...@@ -70,7 +70,7 @@ class Segmentation(Vector):
Mainly 'Maj_count' (Majority Value) and 'Maj_count_perc' (Majority Percent) Mainly 'Maj_count' (Majority Value) and 'Maj_count_perc' (Majority Percent)
@type stats_rpg_tif: dict @type stats_rpg_tif: dict
""" """
def __init__(self, used, cut): def __init__(self, used, cut):
""" """
Create a new 'Clustering' instance Create a new 'Clustering' instance
...@@ -79,10 +79,10 @@ class Segmentation(Vector): ...@@ -79,10 +79,10 @@ class Segmentation(Vector):
self.logger = Outils.Log("Log", "Segmentation") self.logger = Outils.Log("Log", "Segmentation")
Vector.__init__(self, used, cut) Vector.__init__(self, used, cut)
self.stats_rpg_tif = {} self.stats_rpg_tif = {}
self.output_file = 'Final_classification.shp' self.output_file = 'Final_classification.shp'
self.out_class_name = [] self.out_class_name = []
self.out_threshold = dict() self.out_threshold = dict()
...@@ -91,7 +91,7 @@ class Segmentation(Vector): ...@@ -91,7 +91,7 @@ class Segmentation(Vector):
self.max_wood_idm = 0 self.max_wood_idm = 0
self.max_wood_sfs = 0 self.max_wood_sfs = 0
self.max_bio = 0 self.max_bio = 0
def create_cartography(self, out_fieldnames, out_fieldtype): def create_cartography(self, out_fieldnames, out_fieldtype):
""" """
Function to create a output shapefile. In this output file, Function to create a output shapefile. In this output file,
...@@ -103,30 +103,31 @@ class Segmentation(Vector): ...@@ -103,30 +103,31 @@ class Segmentation(Vector):
:param out_fieldtype: List of outpu field type :param out_fieldtype: List of outpu field type
:type out_fieldtype: list of str :type out_fieldtype: list of str
""" """
self.logger.debug("Create output shapefile : {0}".format(self.output_file))
shp_ogr_ds = self.data_source shp_ogr_ds = self.data_source
shp_ogr = self.data_source.GetLayer() shp_ogr = self.data_source.GetLayer()
# Projection # Projection
# Import input shapefile projection # Import input shapefile projection
srsObj = shp_ogr.GetSpatialRef() srsObj = shp_ogr.GetSpatialRef()
# Conversion to syntax ESRI # Conversion to syntax ESRI
srsObj.MorphToESRI() srsObj.MorphToESRI()
## Remove the output final shapefile if it exists ## Remove the output final shapefile if it exists
self.vector_used = self.output_file self.vector_used = self.output_file
if os.path.exists(self.vector_used): if os.path.exists(self.vector_used):
self.data_source.GetDriver().DeleteDataSource(self.vector_used) self.data_source.GetDriver().DeleteDataSource(self.vector_used)
out_ds = self.data_source.GetDriver().CreateDataSource(self.vector_used) out_ds = self.data_source.GetDriver().CreateDataSource(self.vector_used)
if out_ds is None: if out_ds is None:
self.logger.error('Could not create file') self.logger.error('Could not create file')
sys.exit(1) sys.exit(1)
# Specific output layer # Specific output layer
out_layer = out_ds.CreateLayer(self.vector_used, srsObj, geom_type=ogr.wkbMultiPolygon) out_layer = out_ds.CreateLayer(self.vector_used, srsObj, geom_type=ogr.wkbMultiPolygon)
# Add new fields # Add new fields
# To add RPG_CODE field # To add RPG_CODE field
out_fieldnames.insert(2,'RPG_CODE') out_fieldnames.insert(2,'RPG_CODE')
...@@ -143,45 +144,43 @@ class Segmentation(Vector): ...@@ -143,45 +144,43 @@ class Segmentation(Vector):
fieldDefn = ogr.FieldDefn('FBPHY_SUB', ogr.OFTInteger) fieldDefn = ogr.FieldDefn('FBPHY_SUB', ogr.OFTInteger)
out_layer.CreateField(fieldDefn) out_layer.CreateField(fieldDefn)
out_fieldnames.append('FBPHY_SUB') out_fieldnames.append('FBPHY_SUB')
# Feature for the ouput shapefile # Feature for the ouput shapefile
featureDefn = out_layer.GetLayerDefn() featureDefn = out_layer.GetLayerDefn()
in_feature = shp_ogr.SetNextByIndex(0) # Polygons initialisation
in_feature = shp_ogr.GetNextFeature()
# Loop on input polygons # Loop on input polygons
while in_feature: for idx in range(shp_ogr.GetFeatureCount()) :
in_feature = shp_ogr.GetFeature(idx)
geom = in_feature.GetGeometryRef() # Extract input geometry geom = in_feature.GetGeometryRef() # Extract input geometry
# Create a new polygon # Create a new polygon
out_feature = ogr.Feature(featureDefn) out_feature = ogr.Feature(featureDefn)
# Set the polygon geometry and attribute # Set the polygon geometry and attribute
out_feature.SetGeometry(geom) out_feature.SetGeometry(geom)
# Set the existing ID # Set the existing ID
out_feature.SetField(out_fieldnames[0], in_feature.GetField(self.field_names[2])) out_feature.SetField(out_fieldnames[0], in_feature.GetField(self.field_names[2]))
# Set the area # Set the area
out_feature.SetField(out_fieldnames[1], geom.GetArea()/10000) out_feature.SetField(out_fieldnames[1], geom.GetArea()/10000)
# Set the RPG column # Set the RPG column
recouv_crops_RPG = 0 recouv_crops_RPG = 0
pourc_inter = self.stats_rpg_tif[in_feature.GetFID()]['Maj_count_perc'] pourc_inter = self.stats_rpg_tif[in_feature.GetFID()]['Maj_count_perc']
if pourc_inter >= 85: if pourc_inter >= 85:
recouv_crops_RPG = self.stats_rpg_tif[in_feature.GetFID()]['Maj_count'] recouv_crops_RPG = self.stats_rpg_tif[in_feature.GetFID()]['Maj_count']
out_feature.SetField('RPG_CODE', int(recouv_crops_RPG)) out_feature.SetField('RPG_CODE', int(recouv_crops_RPG))
# Set the others polygons fields with the decision tree dictionnary # Set the others polygons fields with the decision tree dictionnary
for i in range(3, len(out_fieldnames)): for i in range(3, len(out_fieldnames)):
# If list stopped it on the second level, complete by empty case # If list stopped it on the second level, complete by empty case
if len(self.class_tab_final[in_feature.GetFID()]) < len(out_fieldnames)-3 and \ if len(self.class_tab_final[in_feature.GetFID()]) < len(out_fieldnames)-3 and \
self.class_tab_final[in_feature.GetFID()] != []: self.class_tab_final[in_feature.GetFID()] != []:
self.class_tab_final[in_feature.GetFID()].insert(len(self.class_tab_final[in_feature.GetFID()])-3,'') # To 3rd level self.class_tab_final[in_feature.GetFID()].insert(len(self.class_tab_final[in_feature.GetFID()])-3,'') # To 3rd level
self.class_tab_final[in_feature.GetFID()].insert(len(self.class_tab_final[in_feature.GetFID()])-3,0) # To degree self.class_tab_final[in_feature.GetFID()].insert(len(self.class_tab_final[in_feature.GetFID()])-3,0) # To degree
try: try:
# To the confusion matrix, replace level ++ by level -- # To the confusion matrix, replace level ++ by level --
if i == len(out_fieldnames)-1: if i == len(out_fieldnames)-1:
...@@ -191,48 +190,44 @@ class Segmentation(Vector): ...@@ -191,48 +190,44 @@ class Segmentation(Vector):
# if self.class_tab_final[in_feature.GetFID()][i-3] == 2: # if self.class_tab_final[in_feature.GetFID()][i-3] == 2:
# Grassland to natural vegetation # Grassland to natural vegetation
# self.class_tab_final[in_feature.GetFID()][i-3] = 1 # self.class_tab_final[in_feature.GetFID()][i-3] = 1
if self.class_tab_final[in_feature.GetFID()][i-3] > 7: if self.class_tab_final[in_feature.GetFID()][i-3] > 7:
# Phytomass to natural vegetation # Phytomass to natural vegetation
self.class_tab_final[in_feature.GetFID()][i-4] = 1 self.class_tab_final[in_feature.GetFID()][i-4] = 1
out_feature.SetField(str(out_fieldnames[i]), self.class_tab_final[in_feature.GetFID()][i-3]) out_feature.SetField(str(out_fieldnames[i]), self.class_tab_final[in_feature.GetFID()][i-3])
except: except:
for i in range(3, len(out_fieldnames)-3): for i in range(3, len(out_fieldnames)-3):
out_feature.SetField(str(out_fieldnames[i]), 'Undefined') out_feature.SetField(str(out_fieldnames[i]), 'Undefined')
out_feature.SetField('FBPHY_CODE', 255) out_feature.SetField('FBPHY_CODE', 255)
out_feature.SetField('FBPHY_SUB', 255) out_feature.SetField('FBPHY_SUB', 255)
# Append polygon to the output shapefile # Append polygon to the output shapefile
out_layer.CreateFeature(out_feature) out_layer.CreateFeature(out_feature)
# Destroy polygons # Destroy polygons
out_feature.Destroy() out_feature.Destroy()
in_feature.Destroy()
# Next polygon
in_feature = shp_ogr.GetNextFeature()
# Close data # Close data
out_ds.Destroy() out_ds.Destroy()
def decision_tree(self, combin_tree): def decision_tree(self, combin_tree):
""" """
Function to build the decision tree. Taking account output threshold and input Function to build the decision tree. Taking account output threshold and input
class name. class name.
@param combin_tree: Decision tree combination @param combin_tree: Decision tree combination
@type combin_tree: list of number class name @type combin_tree: list of number class name
""" """
# Combination tree on a sentence. Every sentence will be in a table. # Combination tree on a sentence. Every sentence will be in a table.
cond_tab = [] cond_tab = []
for ct in combin_tree: for ct in combin_tree:
cond_a = '' # Condition Term cond_a = '' # Condition Term
c = 0 c = 0
while c < len(ct): while c < len(ct):
# Loop on tree combinaison # Loop on tree combinaison
if self.out_threshold[ct[c]] == '' : if self.out_threshold[ct[c]] == '' :
# For interval condition # For interval condition
cond_a = cond_a + 'self.stats_dict[ind_stats][' + str(ct[c]/2) + ']' +\ cond_a = cond_a + 'self.stats_dict[ind_stats][' + str(ct[c]/2) + ']' +\
...@@ -245,7 +240,7 @@ class Segmentation(Vector): ...@@ -245,7 +240,7 @@ class Segmentation(Vector):
c = c + 1 c = c + 1
cond_tab.append(cond_a[:-5]) # Remove the last 'and' cond_tab.append(cond_a[:-5]) # Remove the last 'and'
# Loop on every value # Loop on every value
for ind_stats in range(len(self.stats_dict)): for ind_stats in range(len(self.stats_dict)):
# Loop on decision tree combination. # Loop on decision tree combination.
for cond in cond_tab: for cond in cond_tab:
...@@ -263,19 +258,19 @@ class Segmentation(Vector): ...@@ -263,19 +258,19 @@ class Segmentation(Vector):
for s in combin_tree[cond_tab.index(cond)]] + \ for s in combin_tree[cond_tab.index(cond)]] + \
[combin_tree[cond_tab.index(cond)][len(combin_tree[cond_tab.index(cond)])-1]] + \ [combin_tree[cond_tab.index(cond)][len(combin_tree[cond_tab.index(cond)])-1]] + \
[combin_tree[cond_tab.index(cond)][len(combin_tree[cond_tab.index(cond)])-1]] [combin_tree[cond_tab.index(cond)][len(combin_tree[cond_tab.index(cond)])-1]]
def compute_biomass_density(self, method='SEATH'): def compute_biomass_density(self, method='SEATH'):
""" """
Function to compute the biomass and density distribution. Function to compute the biomass and density distribution.
It returns threshold of biomass level. It returns threshold of biomass level.
@param method: Classification method used. It can set 'SEATH' (by default) or 'RF' @param method: Classification method used. It can set 'SEATH' (by default) or 'RF'
@type method: str @type method: str
""" """
if method == 'SEATH': if method == 'SEATH':
distri = [v[1:] for k, v in self.stats_dict.items() if eval('v[0]' + self.out_threshold[1])] distri = [v[1:] for k, v in self.stats_dict.items() if eval('v[0]' + self.out_threshold[1])]
distri_bio = [] distri_bio = []
distri_den = [] distri_den = []
for b in distri: for b in distri:
...@@ -283,11 +278,11 @@ class Segmentation(Vector): ...@@ -283,11 +278,11 @@ class Segmentation(Vector):
distri_bio.append(b) distri_bio.append(b)
else: else:
distri_den.append(b) distri_den.append(b)
elif method == 'RF': elif method == 'RF':
distri = [v[1:] for k, v in self.stats_dict.items() if not self.out_threshold["PREDICTION"][k] in [0,6,7]] distri = [v[1:] for k, v in self.stats_dict.items() if not self.out_threshold["PREDICTION"][k] in [0,6,7]]
distri_bio = [] distri_bio = []
distri_den = [] distri_den = []
...@@ -299,10 +294,10 @@ class Segmentation(Vector): ...@@ -299,10 +294,10 @@ class Segmentation(Vector):
else: else:
distri_den.append(b) distri_den.append(b)
# Transpose table # Transpose table
t_distri_bio = list(map(list, zip(*distri_bio))) t_distri_bio = list(map(list, zip(*distri_bio)))
t_distri_den = list(map(list, zip(*distri_den))) t_distri_den = list(map(list, zip(*distri_den)))
# Biomass threshold # Biomass threshold
stdmore = (np.mean(t_distri_bio[2]) + np.std(t_distri_bio[2])) / np.max(t_distri_bio[2]) stdmore = (np.mean(t_distri_bio[2]) + np.std(t_distri_bio[2])) / np.max(t_distri_bio[2])
stdless = (np.mean(t_distri_bio[2]) - np.std(t_distri_bio[2])) / np.max(t_distri_bio[2]) stdless = (np.mean(t_distri_bio[2]) - np.std(t_distri_bio[2])) / np.max(t_distri_bio[2])
...@@ -314,21 +309,21 @@ class Segmentation(Vector): ...@@ -314,21 +309,21 @@ class Segmentation(Vector):
wood_sfs = np.array(t_distri_den[0], dtype=np.float64) wood_sfs = np.array(t_distri_den[0], dtype=np.float64)
wood_idm = np.array(t_distri_den[1], dtype=np.float64) wood_idm = np.array(t_distri_den[1], dtype=np.float64)
max_bio = np.array(t_distri_den[2], dtype=np.float64) max_bio = np.array(t_distri_den[2], dtype=np.float64)
self.max_wood_sfs = np.nanmax(wood_sfs) self.max_wood_sfs = np.nanmax(wood_sfs)
self.max_wood_idm = np.nanmax(wood_idm) self.max_wood_idm = np.nanmax(wood_idm)
self.max_bio = np.nanmax(max_bio) self.max_bio = np.nanmax(max_bio)
def append_scale(self, select_class, form): def append_scale(self, select_class, form):
""" """
Function to complete the 'class_tab_final' list with density and biomass information. Function to complete the 'class_tab_final' list with density and biomass information.
This list will be used to build the final shapefile. This list will be used to build the final shapefile.
@param select_class: Class name to add degree @param select_class: Class name to add degree
@type select_class: str @type select_class: str
@param form: Formula to add degree @param form: Formula to add degree
@type form: str @type form: str
""" """
for ind_stats in range(len(self.stats_dict)): for ind_stats in range(len(self.stats_dict)):
...@@ -356,5 +351,3 @@ class Segmentation(Vector): ...@@ -356,5 +351,3 @@ class Segmentation(Vector):
pass pass
except IndexError: except IndexError:
pass pass
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment