#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
© GRID Team, 2021
"""
import pandas
import os
import json
import plotly.graph_objects as go
import plotly
import tqdm
import numpy
from agri_data import data_import
[docs]class CaniculePlot:
"""Cette classe génère une heat map des canicules sur la base des données de Copernicus.
Les données ont été pré-traitées et stockées dans le même répertoire.
"""
def __init__ (self):
self.current = os.path.normcase(os.path.dirname(os.path.realpath(__file__)))
self.file_name='data/full_data_heatwave.json'
self.full_path = os.path.normcase(f'{self.current}/{self.file_name}')
[docs] def read_json (self):
self.df = pandas.read_json(self.full_path, orient='table')
print(self.df)
[docs] def plot_at_date (self):
"""Crée un carte pour un date données
:return: objet json
:rtype: json
"""
date = pandas.to_datetime('2035-01-01')
self.df = self.df.loc[(slice(None), slice(None), date),:]
self.df = self.df.reset_index()
data = go.Densitymapbox(lat=self.df['lat'], lon=self.df['lon'],
z=self.df['HWD_EU_climate'], radius=10)
layout = go.Layout(mapbox_style="open-street-map",
mapbox=dict(bearing=0,center=dict(lat=43.58, lon=4.04),pitch=0, zoom=4),
paper_bgcolor='rgba(61,61,51,0.3)', plot_bgcolor='rgba(0,0,0,0)', font=dict(color='#5cba47'),
height=650
)
fig=go.Figure(data=data, layout=layout)
#fig.write_html("cannicule.html")
plot_json = json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)
return plot_json
[docs] def plot_cursor (self):
"""Crée un carte pour différentes dates avec un slider temporel
(dates définies dans la variable `list_date`)
:return: objet json
:rtype: json
"""
#self.df = self.df.reset_index()
data_slider = []
fig = go.Figure()
list_date = ["2021-01-01", "2031-01-01", "2041-01-01", "2051-01-01", "2061-01-01", "2081-01-01"]
list_date = [pandas.to_datetime(k) for k in list_date]
for date in tqdm.tqdm(list_date):
temp_df = self.df.loc[(slice(None), slice(None), date),:].reset_index()
temp_df['int_days'] = temp_df.apply(lambda x: int(x['HWD_EU_climate']), axis=1)
temp_df['year'] = temp_df.apply(lambda x: x['time'].strftime('%Y'), axis=1)
fig.add_trace(go.Densitymapbox(lat=temp_df['lat'], lon=temp_df['lon'],
z=temp_df['HWD_EU_climate'], radius=10,
colorbar= {'title':'Nb de jours'},
zmin=0, zmax=temp_df['HWD_EU_climate'].max(),
customdata = temp_df[['int_days', 'year']],
hovertemplate = '<b>%{customdata[0]}</b> jours<br>' + "%{customdata[1]} <extra></extra>"
)
)
fig.add_trace(go.Scattermapbox(lat=[43.58], lon=[4.04], marker = {'size': 30, 'color':["#0D9580"]},
hovertemplate = "<b>Exploitation</b> <extra></extra>")) #Agri location
steps = []
for i, date in zip(range(len(fig.data)-1), list_date): #Creation of slider by looping in dates
step = dict(method='update',
args=[{"visible": [False] * (len(fig.data)-1) + [True]}, #Add True at the end to show location
{"title": f"Carte des canicules {date.strftime('%Y')}"}],
label=f"Year: {date.strftime('%Y')}",
)
step["args"][0]["visible"][i] = True
steps.append(step)
sliders = [dict(active=0, pad={"t": 1}, steps=steps)]
fig.update_layout(mapbox_style="open-street-map",
mapbox=dict(bearing=0,center=dict(lat=43.58, lon=4.04),pitch=0, zoom=6),
paper_bgcolor='rgba(61,61,51,0.3)', plot_bgcolor='rgba(0,0,0,0)', font=dict(color='#5cba47'),
height=650, sliders=sliders
)
#fig=go.Figure(data=data_slider, layout=layout)
#fig.write_html("cannicule.html") #utilisé en phase de test
plot_json = json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)
return plot_json
[docs] def main(self):
"""Fonction lançant le tout
:return: objet json
:rtype: json
"""
self.read_json()
plot_json = self.plot_cursor()
return plot_json
[docs]class FirePlot:
"""Cette classe génère une carte avec un scatter plot des risques incendies sur la base des données de Copernicus.
Les données ont été pré-traitées et stockées dans le même répertoire.
"""
def __init__ (self):
self.current = os.path.normcase(os.path.dirname(os.path.realpath(__file__)))
self.file_name='data/full_data_fire.json'
self.full_path = os.path.normcase(f'{self.current}/{self.file_name}')
self.agri_data = data_import.ReadData('data_agri').read_json()
self.lat = self.agri_data['Lat'].iloc[-1] #Agri Lat
self.lon = self.agri_data['Long'].iloc[-1] #Agri Lon
[docs] def read_json (self):
"""Lecture du fichier .json et tri de l'index
"""
self.df = pandas.read_json(self.full_path, orient='table')
self.df = self.df.set_index(['lat','lon', 'time'])
self.df = self.df.sort_index()
print(self.df)
[docs] def color_scale(self, zmax):
"""Cette fonction accomplit 2 choses en parallèle: création d'une echelle de couleurs pour correpondre au Fire Index européen et
trouve les valeurs centrales de chacun des intervalles utilisés pour afficher l'echelle de couleur annotée
:return: liste de l'echelle de couleurs normée (i.e. valeurs entre 0 et 1) et liste du centre des intervalles
:rtype: list
"""
colorscale=[[0.00, '#fee5d9'],
[5.20, '#fcbba1'],
[11.2, '#fc9272'],
[21.3, '#fb6a4a'],
[38.0, '#ef3b2c'],
[50.0, "#cb181d"],
[zmax, "#99000d"],
]
Delta = colorscale[-1][0] - colorscale[0][0]
colorscheme = []
tick_val = []
current_val = colorscale[0][0]
for k in range(len(colorscale)-1):
#First determine the range for a color
delta = colorscale[k+1][0] - colorscale[k][0]
step = delta/Delta
for a_val in numpy.linspace(current_val, current_val+step, num=10, endpoint=False):
colorscheme.append([a_val, colorscale[k][1]])
a_val = 0.99*(colorscale[k+1][0]/colorscale[-1][0])
colorscheme.append([a_val, colorscale[k][1]])
current_val = colorscale[k+1][0]/colorscale[-1][0]
#Define the middle of the range
tick_val.append(colorscale[k][0])
tick_val.append((colorscale[k+1][0] - colorscale[k][0])/2.0+colorscale[k][0] )
colorscheme.append([1.0, colorscale[k][1]]) #Append last value
tick_val.append(int(colorscale[k+1][0])) #Append last value
return colorscheme, tick_val
[docs] def plot_at_date (self):
"""Crée un carte pour une date donnée
:return: objet json
:rtype: json
"""
date = pandas.to_datetime('2097-11-01')
self.df = self.df.loc[(slice(None), slice(None), date),:]
self.df = self.df.reset_index()
data = go.Densitymapbox(lat=self.df['lat'], lon=self.df['lon'],
z=self.df['fwi-mean-jjas'], radius=10)
layout = go.Layout(mapbox_style="open-street-map",
mapbox=dict(bearing=0,center=dict(lat=43.58, lon=4.04),pitch=0, zoom=4),
paper_bgcolor='rgba(61,61,51,0.3)', plot_bgcolor='rgba(0,0,0,0)', font=dict(color='#5cba47'),
height=650
)
fig=go.Figure(data=data, layout=layout)
#fig.write_html("fire.html") #utilisé en phase de test
plot_json = json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)
return plot_json
[docs] def plot_cursor (self):
"""Crée un carte pour différentes dates avec un slider temporel
(dates définies dans la variable `list_date`)
:return: objet json
:rtype: json
"""
fig = go.Figure()
list_date = ["2021-11-01", "2031-11-01", "2041-11-01", "2051-11-01", "2061-11-01", "2081-11-01"]
list_date = [pandas.to_datetime(k) for k in list_date]
partial_df = self.df.loc[(slice(None), slice(None), list_date),:]
zmax = partial_df['fwi-mean-jjas'].max()
colorscheme, tick_val = self.color_scale(zmax)
for date in tqdm.tqdm(list_date):
temp_df = partial_df.loc[(slice(None), slice(None), date),:].reset_index()
temp_df['int_days'] = temp_df.apply(lambda x: round(x['fwi-mean-jjas'],2), axis=1)
temp_df['year'] = temp_df.apply(lambda x: x['time'].strftime('%Y'), axis=1)
fig.add_trace(go.Scattermapbox(lat=temp_df['lat'], lon=temp_df['lon'],
marker = dict(color=temp_df['fwi-mean-jjas'],
size=20,
colorscale = colorscheme,
colorbar= {'title':'Probabilité de feu',
'tickvals':tick_val,
'ticktext':[0, "<b>Très bas</b>", 5.2, "<b>Bas</b>", 11.2, "<b>Modéré</b>", 21.3, "<b>Haut</b>", 38.0, "<b>Très haut</b>", 50.0, "<b>Extrême</b>"],
'ticks':"outside"
},
cmin=0, cmax=zmax, opacity=1
),
customdata = temp_df[['int_days', 'year']],
hovertemplate = '<b>%{customdata[0]}</b> index feu<br>' + "%{customdata[1]} <extra></extra>"
)
)
fig.add_trace(go.Scattermapbox(lat=[self.lat],
lon=[self.lon],
marker = {'size': 30, 'color':["#0D9580"]},
hovertemplate = "<b>Exploitation</b> <extra></extra>")) #Add point for agri
steps = []
for i, date in zip(range(len(fig.data)-1), list_date):
step = dict(method='update',
args=[{"visible": [False] * (len(fig.data)-1) + [True]}, #Keep the last one true b/c agri location
{"title": f"Carte des canicules {date.strftime('%Y')}"}],
label=f"Year: {date.strftime('%Y')}",
)
step["args"][0]["visible"][i] = True #Turn on the one selected by slider
steps.append(step)
sliders = [dict(active=0, pad={"t": 1}, steps=steps)]
fig.update_layout(mapbox_style="open-street-map",
mapbox=dict(bearing=0,center=dict(lat=self.lat, lon=self.lon),pitch=0, zoom=6),
paper_bgcolor='#F8FCF7', plot_bgcolor='rgba(0,0,0,0)', font=dict(color='#5cba47'),
height=650, sliders=sliders, showlegend=False
)
#fig.write_html("fire.html") #utilisé en phase de test
plot_json = json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)
return plot_json
[docs] def main(self):
"""Fonction lançant le tout
:return: objet json
:rtype: json
"""
self.read_json()
plot_json = self.plot_cursor()
return plot_json
if __name__ == '__main__':
canicule = FirePlot().main()