Spaces:
Runtime error
Runtime error
Update app2.py
Browse files
app2.py
CHANGED
|
@@ -70,8 +70,8 @@ if "css_injected" not in st.session_state:
|
|
| 70 |
st.session_state.css_injected = True
|
| 71 |
|
| 72 |
#-------------------------------------------------------- Configuration AWS S3 ---------------------------------------------------
|
| 73 |
-
aws_access_key_id = os.
|
| 74 |
-
aws_secret_access_key = os.
|
| 75 |
aws_region = "eu-west-3"
|
| 76 |
|
| 77 |
s3 = boto3.client(
|
|
@@ -109,20 +109,6 @@ with header:
|
|
| 109 |
# ------------------------------- Tabs ---------------------------------------
|
| 110 |
content = st.container()
|
| 111 |
with content:
|
| 112 |
-
# # CSS des tabs
|
| 113 |
-
# st.markdown("""
|
| 114 |
-
# <style>
|
| 115 |
-
# button[data-baseweb="tab"] {
|
| 116 |
-
# font-size: 20px !important;
|
| 117 |
-
# font-weight: 600;
|
| 118 |
-
# padding: 10px 18px;
|
| 119 |
-
# }
|
| 120 |
-
# button[data-baseweb="tab"][aria-selected="true"] {
|
| 121 |
-
# color: #1f77b4;
|
| 122 |
-
# border-bottom: 3px solid #1f77b4;
|
| 123 |
-
# }
|
| 124 |
-
# </style>
|
| 125 |
-
# """, unsafe_allow_html=True)
|
| 126 |
|
| 127 |
page_tabs = st.tabs([
|
| 128 |
"Notre Projet",
|
|
@@ -152,19 +138,6 @@ def load_model_data() -> pd.DataFrame:
|
|
| 152 |
st.error(f"❌ Erreur chargement dataset météo : {e}")
|
| 153 |
return pd.DataFrame()
|
| 154 |
|
| 155 |
-
|
| 156 |
-
def load_historique_incendies() -> pd.DataFrame:
|
| 157 |
-
bucket = "projet-final-lead"
|
| 158 |
-
key = "data/historique_incendies_avec_coordonnees.csv"
|
| 159 |
-
try:
|
| 160 |
-
obj = s3.get_object(Bucket=bucket, Key=key)
|
| 161 |
-
df = pd.read_csv(obj['Body'], sep=';', encoding='utf-8')
|
| 162 |
-
return df
|
| 163 |
-
except Exception as e:
|
| 164 |
-
st.error(f"❌ Erreur : {e}")
|
| 165 |
-
return pd.DataFrame()
|
| 166 |
-
|
| 167 |
-
|
| 168 |
def load_casernes() -> pd.DataFrame:
|
| 169 |
|
| 170 |
bucket = "projet-final-lead"
|
|
@@ -178,34 +151,6 @@ def load_casernes() -> pd.DataFrame:
|
|
| 178 |
st.error(f"❌ Erreur : {e}")
|
| 179 |
return pd.DataFrame()
|
| 180 |
|
| 181 |
-
|
| 182 |
-
def load_data() -> pd.DataFrame:
|
| 183 |
-
|
| 184 |
-
bucket = "projet-final-lead"
|
| 185 |
-
key = "data/Incendies_2006_2024.csv"
|
| 186 |
-
try:
|
| 187 |
-
obj = s3.get_object(Bucket=bucket, Key=key)
|
| 188 |
-
content = obj["Body"].read().decode("utf-8")
|
| 189 |
-
df = pd.read_csv(StringIO(content), sep=";", encoding="utf-8", skiprows=3)
|
| 190 |
-
return df
|
| 191 |
-
except Exception as e:
|
| 192 |
-
st.error(f"❌ Erreur : {e}")
|
| 193 |
-
return pd.DataFrame()
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
def load_coords() -> pd.DataFrame:
|
| 197 |
-
|
| 198 |
-
bucket = "projet-final-lead"
|
| 199 |
-
key = "data/coordonnees_villes.csv"
|
| 200 |
-
try:
|
| 201 |
-
obj = s3.get_object(Bucket=bucket, Key=key)
|
| 202 |
-
content = obj["Body"].read().decode("utf-8")
|
| 203 |
-
df = pd.read_csv(StringIO(content), sep=",", encoding="utf-8")
|
| 204 |
-
return df
|
| 205 |
-
except Exception as e:
|
| 206 |
-
st.error(f"❌ Erreur : {e}")
|
| 207 |
-
return pd.DataFrame()
|
| 208 |
-
|
| 209 |
#-------------------------------------------------------- Chargement unique du modèle ---------------------------------------------------
|
| 210 |
mlflow.set_tracking_uri("https://djohell-ml-flow.hf.space")
|
| 211 |
|
|
@@ -274,16 +219,23 @@ Le Code forestier encadre leur gestion durable pour protéger la biodiversité,
|
|
| 274 |
|
| 275 |
st.header("🌲 Zoom sur le taux de boisement des différents départements français")
|
| 276 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 277 |
col1, col2, col3 = st.columns([1,1,1])
|
| 278 |
|
| 279 |
with col1:
|
| 280 |
-
st.image("images/puits carbone.png", caption="Puits de carbone", width=
|
| 281 |
|
| 282 |
with col2:
|
| 283 |
-
st.image("images/racines.png", caption="Limitation de l'érosion", width=
|
| 284 |
|
| 285 |
with col3:
|
| 286 |
-
st.image("images/rayonnement.png", caption="Limitation du rayonnement solaire", width=
|
| 287 |
|
| 288 |
st.write("""---""")
|
| 289 |
|
|
@@ -336,204 +288,79 @@ Le Code forestier encadre leur gestion durable pour protéger la biodiversité,
|
|
| 336 |
with page_tabs[1]:
|
| 337 |
st.subheader("🗺️ 1. Visualisation des incendies entre 2006 et 2024")
|
| 338 |
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
|
| 344 |
-
if df_model.empty:
|
| 345 |
-
st.warning("⚠️ Dataset incendies 2006-2024 vide")
|
| 346 |
-
if df_coords.empty:
|
| 347 |
-
st.warning("⚠️ Dataset coordonnées villes vide")
|
| 348 |
-
if df_historique.empty:
|
| 349 |
-
st.warning("⚠️ Dataset historique incendies vide")
|
| 350 |
-
|
| 351 |
-
# ---------------------------------------------------------------
|
| 352 |
-
# Carte des communes
|
| 353 |
|
| 354 |
-
if not df_coords.empty:
|
| 355 |
-
fig = px.scatter_map(
|
| 356 |
-
df_coords,
|
| 357 |
-
lat="latitude",
|
| 358 |
-
lon="longitude",
|
| 359 |
-
hover_name="ville",
|
| 360 |
-
height=800,
|
| 361 |
-
zoom=4.5,
|
| 362 |
-
map_style="carto-positron",
|
| 363 |
-
title="Carte interactive des communes touchées par des incendies (2006-2024)"
|
| 364 |
-
)
|
| 365 |
-
st.plotly_chart(fig, use_container_width=True)
|
| 366 |
-
|
| 367 |
st.write("""---""")
|
| 368 |
|
| 369 |
-
# ------------------------------------------
|
| 370 |
-
# DBSCAN Clustering
|
| 371 |
st.subheader("🔥 2. Détection des clusters d'incendies")
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
kms_per_radian = 6371.0088
|
| 379 |
-
eps_km = 5
|
| 380 |
-
eps = eps_km / kms_per_radian
|
| 381 |
-
|
| 382 |
-
db = DBSCAN(eps=eps, min_samples=20, metric='haversine').fit(coords_rad)
|
| 383 |
-
df_expanded['cluster'] = db.labels_
|
| 384 |
-
|
| 385 |
-
clustered_data = df_expanded[df_expanded['cluster'] != -1]
|
| 386 |
-
|
| 387 |
-
fig = px.scatter_map(
|
| 388 |
-
clustered_data,
|
| 389 |
-
lat="latitude",
|
| 390 |
-
lon="longitude",
|
| 391 |
-
color="cluster",
|
| 392 |
-
hover_name="Nom de la commune",
|
| 393 |
-
zoom=5,
|
| 394 |
-
height=800,
|
| 395 |
-
title="🔥 Clusters d'incendies en France (2006-2024) détectés par DBSCAN",
|
| 396 |
-
map_style="carto-positron"
|
| 397 |
-
)
|
| 398 |
-
st.plotly_chart(fig, use_container_width=True)
|
| 399 |
|
| 400 |
-
|
| 401 |
-
📌 **À retenir**
|
| 402 |
-
Ce graphique met en évidence une forte hétérogénéité territoriale.
|
| 403 |
-
Les départements les plus touchés concentrent une part disproportionnée des incendies, ce qui motive une approche prédictive ciblée.
|
| 404 |
-
""")
|
| 405 |
|
| 406 |
st.write("""---""")
|
| 407 |
|
| 408 |
# ---------------------------------------------------------------
|
| 409 |
# Histogramme mensuel
|
| 410 |
st.subheader("3. Cumul des incendies mensuels par année")
|
| 411 |
-
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
mois_abbr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
| 419 |
-
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
| 420 |
-
df_temp['mois_nom'] = df_temp['mois'].apply(lambda x: mois_abbr[x - 1])
|
| 421 |
-
df_temp['mois_nom'] = pd.Categorical(df_temp['mois_nom'], categories=mois_abbr, ordered=True)
|
| 422 |
-
|
| 423 |
-
df_grouped = df_temp.groupby(['mois_nom', 'année']).size().reset_index(name='nombre_feux')
|
| 424 |
-
|
| 425 |
-
fig = px.bar(
|
| 426 |
-
df_grouped,
|
| 427 |
-
x='mois_nom',
|
| 428 |
-
y='nombre_feux',
|
| 429 |
-
color='année',
|
| 430 |
-
barmode='group',
|
| 431 |
-
height=600,
|
| 432 |
-
width=1000
|
| 433 |
-
)
|
| 434 |
-
st.plotly_chart(fig, use_container_width=True)
|
| 435 |
|
| 436 |
-
|
| 437 |
-
""")
|
| 438 |
|
| 439 |
st.write("""---""")
|
| 440 |
|
| 441 |
st.subheader("4. Analyse des causes 🔥")
|
| 442 |
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
# ---------------------------------------------------- Répartition des causes --------------------------------------------
|
| 449 |
-
if "Nature" in df_histo.columns:
|
| 450 |
-
causes = df_histo['Nature'].value_counts()
|
| 451 |
-
|
| 452 |
-
fig, ax = plt.subplots(figsize=(3.5, 3.5), dpi=80)
|
| 453 |
-
ax.pie(
|
| 454 |
-
causes.values,
|
| 455 |
-
labels=causes.index,
|
| 456 |
-
autopct='%1.0f%%',
|
| 457 |
-
startangle=140
|
| 458 |
-
)
|
| 459 |
-
|
| 460 |
-
ax.axis('equal')
|
| 461 |
-
|
| 462 |
-
col1, col2, col3 = st.columns([1, 1, 1])
|
| 463 |
-
|
| 464 |
-
with col2:
|
| 465 |
-
st.pyplot(fig)
|
| 466 |
-
else:
|
| 467 |
-
st.warning("⚠️ La colonne 'Nature' est absente du DataFrame.")
|
| 468 |
|
| 469 |
-
|
| 470 |
-
|
| 471 |
-
|
| 472 |
|
| 473 |
-
|
| 474 |
|
| 475 |
# ---------------------------------------------------- Nombre total d’incendies par année ----------------------------------
|
| 476 |
-
|
| 477 |
-
|
| 478 |
-
|
| 479 |
-
|
| 480 |
-
|
| 481 |
-
|
| 482 |
-
|
| 483 |
-
|
| 484 |
-
fig = px.bar(
|
| 485 |
-
df_grouped,
|
| 486 |
-
x='année',
|
| 487 |
-
y='nombre_feux',
|
| 488 |
-
height=600,
|
| 489 |
-
text='nombre_feux'
|
| 490 |
-
)
|
| 491 |
-
fig.update_xaxes(tickmode='linear', dtick=1)
|
| 492 |
-
fig.update_layout(xaxis_title='Année', yaxis_title='Nombre de feux', xaxis_tickangle=0)
|
| 493 |
-
st.plotly_chart(fig)
|
| 494 |
-
else:
|
| 495 |
-
st.warning("⚠️ La colonne 'Date' est absente du DataFrame.")
|
| 496 |
-
|
| 497 |
-
st.info("""L'année 2022 fut une année noire avec un nombre record d'incendies, notamment une surface brûlée de 60 000 ha, soit l'équivalent de
|
| 498 |
84 000 terrains de football, ou encore 5,7 fois la surface de Paris intra-muros.""")
|
| 499 |
|
| 500 |
# ---------------------------------------------------- Top départements
|
| 501 |
st.subheader("6. Les 10 départements les plus touchés 🔥")
|
| 502 |
|
| 503 |
-
|
| 504 |
-
|
| 505 |
-
|
| 506 |
-
|
| 507 |
-
|
| 508 |
-
|
| 509 |
-
st.error("❌ La colonne 'Département' est absente du DataFrame.")
|
| 510 |
-
else:
|
| 511 |
-
# Regroupement par département
|
| 512 |
-
df_grouped = df_temp.groupby('Département').size().reset_index(name='nombre_feux')
|
| 513 |
-
|
| 514 |
-
# Classement décroissant et sélection du top 10
|
| 515 |
-
df_top10 = df_grouped.sort_values(by='nombre_feux', ascending=False).head(10)
|
| 516 |
-
|
| 517 |
-
# Graphique en barres
|
| 518 |
-
fig = px.bar(
|
| 519 |
-
df_top10,
|
| 520 |
-
x='Département',
|
| 521 |
-
y='nombre_feux',
|
| 522 |
-
height=600,
|
| 523 |
-
width=1000,
|
| 524 |
-
text='nombre_feux'
|
| 525 |
-
)
|
| 526 |
-
|
| 527 |
-
fig.update_layout(
|
| 528 |
-
template='plotly_white',
|
| 529 |
-
xaxis_title='Département',
|
| 530 |
-
yaxis_title='Nombre de feux',
|
| 531 |
-
xaxis_tickangle=-45,
|
| 532 |
-
)
|
| 533 |
-
|
| 534 |
-
fig.update_traces(textposition='outside')
|
| 535 |
-
|
| 536 |
-
st.plotly_chart(fig)
|
| 537 |
|
| 538 |
st.info("""Après analyse, la Corse se démarque nettement comme le département le plus touché par les incendies de forêt en France, justifiant ainsi notre choix de focus pour la suite de notre projet.""")
|
| 539 |
|
|
|
|
| 70 |
st.session_state.css_injected = True
|
| 71 |
|
| 72 |
#-------------------------------------------------------- Configuration AWS S3 ---------------------------------------------------
|
| 73 |
+
aws_access_key_id = os.getenv("AWS_ACCESS_KEY_ID")
|
| 74 |
+
aws_secret_access_key = os.getenv("AWS_SECRET_ACCESS_KEY")
|
| 75 |
aws_region = "eu-west-3"
|
| 76 |
|
| 77 |
s3 = boto3.client(
|
|
|
|
| 109 |
# ------------------------------- Tabs ---------------------------------------
|
| 110 |
content = st.container()
|
| 111 |
with content:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
|
| 113 |
page_tabs = st.tabs([
|
| 114 |
"Notre Projet",
|
|
|
|
| 138 |
st.error(f"❌ Erreur chargement dataset météo : {e}")
|
| 139 |
return pd.DataFrame()
|
| 140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
def load_casernes() -> pd.DataFrame:
|
| 142 |
|
| 143 |
bucket = "projet-final-lead"
|
|
|
|
| 151 |
st.error(f"❌ Erreur : {e}")
|
| 152 |
return pd.DataFrame()
|
| 153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
#-------------------------------------------------------- Chargement unique du modèle ---------------------------------------------------
|
| 155 |
mlflow.set_tracking_uri("https://djohell-ml-flow.hf.space")
|
| 156 |
|
|
|
|
| 219 |
|
| 220 |
st.header("🌲 Zoom sur le taux de boisement des différents départements français")
|
| 221 |
|
| 222 |
+
col1, col2, col3 = st.columns([1, 2, 1])
|
| 223 |
+
with col2:
|
| 224 |
+
st.image("images/boisement.png", caption="Taux de boisement par département en France en 2024 (source : IGN)", use_container_width=True)
|
| 225 |
+
|
| 226 |
+
st.write("""---""")
|
| 227 |
+
|
| 228 |
+
st.header(" Quels sont les principaux rôles de la forêt ?")
|
| 229 |
col1, col2, col3 = st.columns([1,1,1])
|
| 230 |
|
| 231 |
with col1:
|
| 232 |
+
st.image("images/puits carbone.png", caption="Puits de carbone", width=400)
|
| 233 |
|
| 234 |
with col2:
|
| 235 |
+
st.image("images/racines.png", caption="Limitation de l'érosion", width=500)
|
| 236 |
|
| 237 |
with col3:
|
| 238 |
+
st.image("images/rayonnement.png", caption="Limitation du rayonnement solaire", width=400)
|
| 239 |
|
| 240 |
st.write("""---""")
|
| 241 |
|
|
|
|
| 288 |
with page_tabs[1]:
|
| 289 |
st.subheader("🗺️ 1. Visualisation des incendies entre 2006 et 2024")
|
| 290 |
|
| 291 |
+
image = Image.open("images/incendies.png")
|
| 292 |
+
st.image(
|
| 293 |
+
image,
|
| 294 |
+
use_container_width=True
|
| 295 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 296 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 297 |
st.write("""---""")
|
| 298 |
|
| 299 |
+
# ----------- DBSCAN Clustering -------------------------------
|
|
|
|
| 300 |
st.subheader("🔥 2. Détection des clusters d'incendies")
|
| 301 |
+
|
| 302 |
+
image = Image.open("images/clustering.png")
|
| 303 |
+
st.image(
|
| 304 |
+
image,
|
| 305 |
+
use_container_width=True
|
| 306 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 307 |
|
| 308 |
+
st.info("""
|
| 309 |
+
📌 **À retenir**
|
| 310 |
+
Ce graphique met en évidence une forte hétérogénéité territoriale.
|
| 311 |
+
Les départements les plus touchés concentrent une part disproportionnée des incendies, ce qui motive une approche prédictive ciblée.
|
| 312 |
+
""")
|
| 313 |
|
| 314 |
st.write("""---""")
|
| 315 |
|
| 316 |
# ---------------------------------------------------------------
|
| 317 |
# Histogramme mensuel
|
| 318 |
st.subheader("3. Cumul des incendies mensuels par année")
|
| 319 |
+
|
| 320 |
+
image = Image.open("images/saison.png")
|
| 321 |
+
st.image(
|
| 322 |
+
image,
|
| 323 |
+
use_container_width=True
|
| 324 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 325 |
|
| 326 |
+
st.info(""" Sans grande surprise, on observe une saisonnalité marquée des incendies, avec un pic significatif durant les mois de juillet et août.
|
| 327 |
+
""")
|
| 328 |
|
| 329 |
st.write("""---""")
|
| 330 |
|
| 331 |
st.subheader("4. Analyse des causes 🔥")
|
| 332 |
|
| 333 |
+
image = Image.open("images/causes.png")
|
| 334 |
+
st.image(
|
| 335 |
+
image,
|
| 336 |
+
use_container_width=True
|
| 337 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 338 |
|
| 339 |
+
st.info("""
|
| 340 |
+
📌 **À retenir** :
|
| 341 |
+
L’analyse des causes révèle que la majorité des incendies sont d’origine humaine, soulignant l’importance de la prévention et de la sensibilisation pour réduire ces incidents.""")
|
| 342 |
|
| 343 |
+
st.write("""---""")
|
| 344 |
|
| 345 |
# ---------------------------------------------------- Nombre total d’incendies par année ----------------------------------
|
| 346 |
+
image = Image.open("images/cumul_annuel.png")
|
| 347 |
+
st.image(
|
| 348 |
+
image,
|
| 349 |
+
use_container_width=True
|
| 350 |
+
)
|
| 351 |
+
|
| 352 |
+
st.info("""L'année 2022 fut une année noire avec un nombre record d'incendies, notamment une surface brûlée de 60 000 ha, soit l'équivalent de
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 353 |
84 000 terrains de football, ou encore 5,7 fois la surface de Paris intra-muros.""")
|
| 354 |
|
| 355 |
# ---------------------------------------------------- Top départements
|
| 356 |
st.subheader("6. Les 10 départements les plus touchés 🔥")
|
| 357 |
|
| 358 |
+
image = Image.open("images/departement.png")
|
| 359 |
+
st.image(
|
| 360 |
+
image,
|
| 361 |
+
caption="Top 10 des départements les plus touchés par les incendies",
|
| 362 |
+
use_container_width=True
|
| 363 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 364 |
|
| 365 |
st.info("""Après analyse, la Corse se démarque nettement comme le département le plus touché par les incendies de forêt en France, justifiant ainsi notre choix de focus pour la suite de notre projet.""")
|
| 366 |
|