wildfire / app.py
MohammadAlDalo's picture
Update app.py
4766aab verified
Raw
History Blame Contribute Delete
5.64 kB
from fastapi import FastAPI
from fastapi.responses import FileResponse, HTMLResponse
from fastapi.staticfiles import StaticFiles
import folium
import pandas as pd
import joblib
import os
import requests
app = FastAPI()
# ===============================
# Serve static files
# ===============================
app.mount("/static", StaticFiles(directory="."), name="static")
# ===============================
# Load ML Model
# ===============================
model = None
model_paths = [
"wildfire_model_cyprus.pkl",
"models/wildfire_model_cyprus.pkl",
]
for path in model_paths:
if os.path.exists(path):
model = joblib.load(path)
print(f"✅ Model loaded from: {path}")
break
MAP_FILE = "cyprus_wildfire_risk_map.html"
# ===============================
# Cyprus Cities
# ===============================
cities = {
"Nicosia": (35.1856, 33.3823),
"Limassol": (34.7071, 33.0226),
"Larnaca": (34.9182, 33.6233),
"Paphos": (34.7754, 32.4218),
"Famagusta": (35.1167, 33.9500),
"Kyrenia": (35.3417, 33.3167),
"Morphou": (35.1989, 32.9931),
"Lapta": (35.3389, 33.1611),
"Alsancak": (35.3444, 33.1936),
"Dikmen": (35.2681, 33.3408),
"Değirmenlik": (35.2897, 33.4356),
"Geçitkale": (35.2606, 33.7922),
"Iskele": (35.2722, 33.9458),
"Geroskipou": (34.7567, 32.4547),
"Chloraka": (34.8075, 32.4064),
"Ypsonas": (34.6889, 32.9556),
"Kato Polemidia": (34.6967, 33.0111),
"Aradippou": (34.9517, 33.5928),
"Athienou": (35.0608, 33.5419),
"Polis": (35.0367, 32.4250),
"Peyia": (34.8833, 32.3833),
"Kathikas": (34.9175, 32.4686),
"Ayia Napa": (34.9889, 34.0018),
"Paralimni": (35.0394, 33.9819),
"Deryneia": (35.0648, 33.9566),
"Kakopetria": (34.9894, 32.9033),
"Platres": (34.8633, 32.8575),
}
# ===============================
# Home Page
# ===============================
@app.get("/", response_class=HTMLResponse)
def home():
return """
<html>
<head>
<title>Cyprus Wildfire Risk</title>
</head>
<body style="font-family: Arial; text-align:center;">
<h1>🔥 Cyprus Wildfire Risk Map</h1>
<form action="/generate-map" method="post">
<button style="padding:15px;font-size:18px;">
Generate Wildfire Map
</button>
</form>
<br><br>
<a href="/view-map">View Map</a>
</body>
</html>
"""
# ===============================
# Generate Map
# ===============================
@app.post("/generate-map")
def generate_map():
if model is None:
return {"error": "Model not loaded"}
m = folium.Map(location=[35.1, 33.4], zoom_start=8)
for city, (lat, lon) in cities.items():
# ===============================
# REAL WEATHER API CALL
# ===============================
url = (
"https://api.open-meteo.com/v1/forecast"
f"?latitude={lat}"
f"&longitude={lon}"
"&hourly=temperature_2m,relative_humidity_2m,wind_speed_100m,precipitation"
"&forecast_days=7"
"&timezone=auto"
)
try:
response = requests.get(url, timeout=8)
data = response.json()
hourly = data["hourly"]
# 3-day averages
temp = sum(hourly["temperature_2m"][:72]) / 72
humidity = sum(hourly["relative_humidity_2m"][:72]) / 72
wind = sum(hourly["wind_speed_100m"][:72]) / 72
# 7-day rainfall
rainfall = sum(hourly["precipitation"][:168])
except Exception as e:
print("Weather API failed:", e)
temp = 30
humidity = 50
wind = 12
rainfall = 5
# ===============================
# Prepare ML Input
# ===============================
X = pd.DataFrame({
"temp_c": [temp],
"humidity": [humidity],
"wind_speed": [wind],
"precipitation": [0],
"temp_3d_avg": [temp],
"humidity_3d_avg": [humidity],
"precipitation_7d": [rainfall],
"wind_3d_avg": [wind]
})
prediction = model.predict(X)[0]
# ===============================
# Risk Classification
# ===============================
if prediction == 1 or (temp > 32 and humidity < 35):
color = "red"
risk = "High Risk"
elif temp > 28 and humidity < 45 and rainfall < 10:
color = "orange"
risk = "Medium Risk"
else:
color = "green"
risk = "Low Risk"
# ===============================
# Add marker to map
# ===============================
folium.CircleMarker(
location=[lat, lon],
radius=7,
color=color,
fill=True,
fill_color=color,
fill_opacity=0.8,
popup=f"""
<b>{city}</b><br>
Temperature: {temp:.1f} °C<br>
Humidity: {humidity:.1f}%<br>
Wind Speed: {wind:.1f} km/h<br>
Rainfall (7d): {rainfall:.1f} mm<br>
<b>{risk}</b>
"""
).add_to(m)
m.save(MAP_FILE)
return {"status": "map generated", "view": "/view-map"}
# ===============================
# View Map
# ===============================
@app.get("/view-map")
def view_map():
if os.path.exists(MAP_FILE):
return FileResponse(MAP_FILE)
return {"error": "Generate map first"}