Commit 5b0564c8 authored by Dumoulin Nicolas's avatar Dumoulin Nicolas
Browse files

class Indicators introduced for better performance (not reloaded for each evaluation)

parent d96a7825
...@@ -26,6 +26,38 @@ from EPCI_culture_repartition import EPCI_culture_repartition ...@@ -26,6 +26,38 @@ from EPCI_culture_repartition import EPCI_culture_repartition
from radar import scenarios_graph from radar import scenarios_graph
class Indicators:
def __init__(self, mcmc_config_filename, initial_patches):
if not os.path.isfile(mcmc_config_filename):
print('Error: file not found "{}"'.format(mcmc_config_filename))
print('Please copy the template file "MCMC_config.sample.yml" and adjust to your settings and run again this program')
sys.exit(1)
self.mcmc_config = yaml.load(open(mcmc_config_filename,'r'))
self._proximity = Proximite(initial_patches, self.mcmc_config['indicators_config']['proximite']['surf_totale_cible'])
self._resilience = Resilience(self.mcmc_config['indicators_config']['resilience'])
self._productivity = Productivity()
biodiv_config = self.mcmc_config['indicators_config']['biodiversity']
matrixfilename = biodiv_config['matrixfilename']
self._biodiversity = Biodiversity(initial_patches, biodiv_config['dmax'], biodiv_config['epsilon'])
self._biodiversity.load_probabilities(matrixfilename)
social_config = self.mcmc_config['indicators_config']['social']
self._social = Social(initial_patches, social_config['cost_matrix_filename'], social_config['bdv_threshold'])
def proximity(self, patches):
return self._proximity.compute_indicator(patches, False)
def resilience(self, patches):
return self._resilience.compute_indicator(patches, False)
def productivity(self, patches):
return self._productivity.compute_indicator(patches)
def biodiversity(self, patches):
return self._biodiversity.compute_indicator(patches)
def social(self, patches):
return self._social.compute_indicator(patches)
class Scenario : class Scenario :
''' '''
This class is used to create a new randomized scenario from an initial scenario. A few functions are included to permit This class is used to create a new randomized scenario from an initial scenario. A few functions are included to permit
...@@ -66,7 +98,7 @@ class Scenario : ...@@ -66,7 +98,7 @@ class Scenario :
if culture == "Protéagineux" : if culture == "Protéagineux" :
return 6 return 6
def __init__(self, scenarioInitial, nbr_parcelles_a_modifier, cereales, culturesI, fourrages, fruits_legumes, oleagineux, prairies, proteagineux, liste, rng) : def __init__(self, indicators, scenarioInitial, nbr_parcelles_a_modifier, cereales, culturesI, fourrages, fruits_legumes, oleagineux, prairies, proteagineux, liste, rng) :
''' '''
Create a new randomized scenario according to the parameters Create a new randomized scenario according to the parameters
...@@ -86,15 +118,10 @@ class Scenario : ...@@ -86,15 +118,10 @@ class Scenario :
self.oleagineux = oleagineux self.oleagineux = oleagineux
self.prairies = prairies self.prairies = prairies
self.proteagineux = proteagineux self.proteagineux = proteagineux
mcmc_config_filename = 'MCMC_config.yml'
if not os.path.isfile(mcmc_config_filename): self.indicators = indicators
print('Error: file not found "{}"'.format(mcmc_config_filename))
print('Please copy the template file "MCMC_config.sample.yml" and adjust to your settings and run again this program')
sys.exit(1)
self.mcmc_config = yaml.load(open(mcmc_config_filename,'r'))
self.initial_patches = gpd.GeoDataFrame.from_file(scenarioInitial, encoding='utf-8') self.initial_patches = gpd.GeoDataFrame.from_file(scenarioInitial, encoding='utf-8')
self.proximite = Proximite(self.initial_patches, self.mcmc_config['indicators_config']['proximite']['surf_totale_cible'])
# If ScenarioInitial is a filename -> transform it in a list # If ScenarioInitial is a filename -> transform it in a list
if liste == False : if liste == False :
...@@ -258,6 +285,7 @@ class Scenario : ...@@ -258,6 +285,7 @@ class Scenario :
# Sort the final list to make it ordered as the same way of the initial list # Sort the final list to make it ordered as the same way of the initial list
resultat_final = sorted(resultat_final, key=lambda k: k['properties']['ID_PARCEL']) resultat_final = sorted(resultat_final, key=lambda k: k['properties']['ID_PARCEL'])
self.resultat_final = resultat_final self.resultat_final = resultat_final
self.resultat_final_gpd = gpd.GeoDataFrame.from_features(resultat_final)
...@@ -304,7 +332,6 @@ class Scenario : ...@@ -304,7 +332,6 @@ class Scenario :
Write the values of indices of the initial scenario in a JSON file Write the values of indices of the initial scenario in a JSON file
This function is used for display and statistics in the application This function is used for display and statistics in the application
''' '''
indicators = self.mcmc_config['indicators_config']
dict_indices = {} dict_indices = {}
dict_indices["proximite"] = self.indice_proximite() dict_indices["proximite"] = self.indice_proximite()
dict_indices["resilience"] = self.indice_resilience() dict_indices["resilience"] = self.indice_resilience()
...@@ -321,42 +348,19 @@ class Scenario : ...@@ -321,42 +348,19 @@ class Scenario :
These functions returns values of indices of this scenario These functions returns values of indices of this scenario
''' '''
def indice_proximite(self) : def indice_proximite(self) :
patches = gpd.GeoDataFrame.from_features(self.resultat_final) return self.indicators.proximity(self.resultat_final_gpd)
indice_prox = self.proximite.compute_indicator(patches, self.fruits_legumes, False)
#print "Résultats de l'indice de proximité : " + str(indice_prox)
return indice_prox
def indice_resilience(self): def indice_resilience(self):
resilience = Resilience(self.mcmc_config['indicators_config']['resilience']) return self.indicators.resilience(self.resultat_final_gpd)
patches = gpd.GeoDataFrame.from_features(self.resultat_final)
indice_resi = resilience.compute_indicator(patches, False)
#print "Résultats de l'indice de résilience : " + str(indice_resi)
return indice_resi
def indice_productivitee(self): def indice_productivitee(self):
productivity = Productivity() return self.indicators.productivity(self.resultat_final_gpd)
patches = gpd.GeoDataFrame.from_features(self.resultat_final)
indice_prod = productivity.compute_indicator(patches)
#print "Résultats de l'indice de productivite : " + str(indice_prod)
return indice_prod
def indice_biodiversite(self): def indice_biodiversite(self):
#Matrix containing all the data about biodiversity. Created with Numpy and the formula of Equivalent Connected Area (Saura et al., 2011) return self.indicators.biodiversity(self.resultat_final_gpd)
biodiv_config = self.mcmc_config['indicators_config']['biodiversity']
matrixfilename = biodiv_config['matrixfilename']
biodiversity = Biodiversity(self.initial_patches, biodiv_config['dmax'], biodiv_config['epsilon'])
biodiversity.load_probabilities(matrixfilename)
patches = gpd.GeoDataFrame.from_features(self.resultat_final)
indice_bio = biodiversity.compute_indicator(patches)
#print "Résultats de l'indice de biodiversite : " + str(indice_bio)
return indice_bio
def indice_social(self): def indice_social(self):
social_config = self.mcmc_config['indicators_config']['social'] return self.indicators.social(self.resultat_final_gpd)
social = Social(social_config['cost_matrix_filename'], social_config['bdv_threshold'])
indice_social = social.compute_indicator(gpd.GeoDataFrame.from_features(self.shape), gpd.GeoDataFrame.from_features(self.resultat_final))
#print "Résultats de l'indice de sociabilité : " + str(indice_social)
return indice_social
dict_scenario = {} # Contains all scenarios created by the function "générer_x_scenarios" dict_scenario = {} # Contains all scenarios created by the function "générer_x_scenarios"
...@@ -879,8 +883,9 @@ if __name__ == '__main__': ...@@ -879,8 +883,9 @@ if __name__ == '__main__':
# scenarInitial, nbr_loop, nbr_scenario, nbr_scenario_to_stock, nbr_parcelles_a_modifier, cereales, culturesI, fourrages, fruits_legumes, oleagineux, prairies, proteagineux # scenarInitial, nbr_loop, nbr_scenario, nbr_scenario_to_stock, nbr_parcelles_a_modifier, cereales, culturesI, fourrages, fruits_legumes, oleagineux, prairies, proteagineux
#scenario_initial = Scenario("./Parcelle_PAT_MCMC.shp",0, cereales, culturesI, fourrages, fruits_legumes, oleagineux, prairies, proteagineux, False, rng) #scenario_initial = Scenario("./Parcelle_PAT_MCMC.shp",0, cereales, culturesI, fourrages, fruits_legumes, oleagineux, prairies, proteagineux, False, rng)
scenario_initial = Scenario("../output/PAT_patches/PAT_patches.shp",0, cereales, culturesI, fourrages, fruits_legumes, oleagineux, prairies, proteagineux, False, rng) patches = gpd.GeoDataFrame.from_file("../output/PAT_patches/PAT_patches.shp", encoding='utf-8')
indicators = Indicators('MCMC_config.yml', patches)
scenario_initial = Scenario(indicators,"../output/PAT_patches/PAT_patches.shp",0, cereales, culturesI, fourrages, fruits_legumes, oleagineux, prairies, proteagineux, False, rng)
#scenario_initial = Scenario("../output/patches_RiomLimagneVolcans.shp",0, cereales, culturesI, fourrages, fruits_legumes, oleagineux, prairies, proteagineux, False, rng) #scenario_initial = Scenario("../output/patches_RiomLimagneVolcans.shp",0, cereales, culturesI, fourrages, fruits_legumes, oleagineux, prairies, proteagineux, False, rng)
scenario_initial.write_indices_in_json() scenario_initial.write_indices_in_json()
scenario_initial.write_indices_in_json()
#MCMC("./Parcelle_PAT_MCMC.shp", 2, 11, 2, nbr_parcelles_a_modifier, cereales, culturesI, fourrages, fruits_legumes, oleagineux, prairies, proteagineux, rng) #MCMC("./Parcelle_PAT_MCMC.shp", 2, 11, 2, nbr_parcelles_a_modifier, cereales, culturesI, fourrages, fruits_legumes, oleagineux, prairies, proteagineux, rng)
...@@ -11,12 +11,12 @@ class Proximite: ...@@ -11,12 +11,12 @@ class Proximite:
''' '''
def __init__(self, initial_patches, surf_totale_cible) : def __init__(self, initial_patches, surf_totale_cible) :
Population_PAT = initial_patches.groupby('INSEE_COM')['POPULATION'].first().sum() #498873 Population_PAT = initial_patches.groupby('INSEE_COM')['POPULATION'].first().sum() #498873
popByBdv = patches.groupby('Bdv').apply(lambda x:x.groupby('INSEE_COM')['POPULATION'].first().sum()) popByBdv = initial_patches.groupby('Bdv').apply(lambda x:x.groupby('INSEE_COM')['POPULATION'].first().sum())
# OK but slower # OK but slower
# popByBdv = patches.groupby(['Bdv','INSEE_COM']).first().groupby('Bdv')['POPULATION'].sum() # popByBdv = patches.groupby(['Bdv','INSEE_COM']).first().groupby('Bdv')['POPULATION'].sum()
self.targetSurfByBdv = surf_totale_cible * popByBdv/Population_PAT self.targetSurfByBdv = surf_totale_cible * popByBdv/Population_PAT
def compute_indicator(self, patches, fruit_legumes, affichage): def compute_indicator(self, patches, affichage):
''' '''
:param shape: The scenario to analyse as a list :param shape: The scenario to analyse as a list
:param fruit_legume: The proportion of area we want in the PAT for the "fruits and vegetables" type :param fruit_legume: The proportion of area we want in the PAT for the "fruits and vegetables" type
...@@ -33,4 +33,4 @@ if __name__ == '__main__': ...@@ -33,4 +33,4 @@ if __name__ == '__main__':
import geopandas as gpd import geopandas as gpd
patches = gpd.GeoDataFrame.from_file("../output/PAT_patches/PAT_patches.shp", encoding='utf-8') patches = gpd.GeoDataFrame.from_file("../output/PAT_patches/PAT_patches.shp", encoding='utf-8')
prox = Proximite(patches, 20165939.605135553) prox = Proximite(patches, 20165939.605135553)
print(prox.compute_indicator(patches, 3, True)) print(prox.compute_indicator(patches, True))
...@@ -12,7 +12,7 @@ class Social: ...@@ -12,7 +12,7 @@ class Social:
These values were defined during reunions and with the review of our experts. These values were defined during reunions and with the review of our experts.
''' '''
def __init__(self, cost_matrix_filename, bdv_threshold): def __init__(self, initial_patches, cost_matrix_filename, bdv_threshold):
''' '''
:param cost_matrix_filename input file containing the matrix in CSV format (separator: \t) :param cost_matrix_filename input file containing the matrix in CSV format (separator: \t)
:param bdv_threshold proportion of a cultural type needed for considering that this cultural type :param bdv_threshold proportion of a cultural type needed for considering that this cultural type
...@@ -20,8 +20,9 @@ class Social: ...@@ -20,8 +20,9 @@ class Social:
''' '''
self.matrice_transition = pd.read_csv(cost_matrix_filename, sep='\t',index_col=0) self.matrice_transition = pd.read_csv(cost_matrix_filename, sep='\t',index_col=0)
self.bdv_threshold = bdv_threshold self.bdv_threshold = bdv_threshold
self.initial_patches = initial_patches[['ID_PARCEL','cultgeopat']]
def compute_indicator(self, initial_patches, scenario_patches): def compute_indicator(self, scenario_patches):
''' '''
:param initial_patches: Initial patches :param initial_patches: Initial patches
:param scenario: The scenario to analyse :param scenario: The scenario to analyse
...@@ -29,7 +30,7 @@ class Social: ...@@ -29,7 +30,7 @@ class Social:
cost = 0 cost = 0
filter1 = pd.merge( filter1 = pd.merge(
scenario_patches[['ID_PARCEL','cultgeopat','Bdv','SURF_PARC','id_expl']], scenario_patches[['ID_PARCEL','cultgeopat','Bdv','SURF_PARC','id_expl']],
initial_patches[['ID_PARCEL','cultgeopat']], self.initial_patches,
on='ID_PARCEL') on='ID_PARCEL')
for bdv,grouped in filter1.groupby('Bdv'): for bdv,grouped in filter1.groupby('Bdv'):
grouped=grouped.copy() grouped=grouped.copy()
...@@ -49,6 +50,6 @@ if __name__ == '__main__': ...@@ -49,6 +50,6 @@ if __name__ == '__main__':
patches = gpd.GeoDataFrame.from_file("../output/PAT_patches/PAT_patches.shp", encoding='utf-8') patches = gpd.GeoDataFrame.from_file("../output/PAT_patches/PAT_patches.shp", encoding='utf-8')
scenario_patches = patches.copy() scenario_patches = patches.copy()
scenario_patches.ix[2,'cultgeopat']='Protéagineux' scenario_patches.ix[2,'cultgeopat']='Protéagineux'
social = Social('../resources/matrice_transition.csv', 0.1) social = Social(patches, '../resources/matrice_transition.csv', 0.1)
print(social.compute_indicator(patches, scenario_patches)) print(social.compute_indicator(scenario_patches))
# should give 0.5 the cost for one transition to Protéagineux # should give 0.5 the cost for one transition to Protéagineux
Markdown is supported
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