|
|
import streamlit as st |
|
|
import pandas as pd |
|
|
import numpy as np |
|
|
import joblib |
|
|
import json |
|
|
import folium |
|
|
from streamlit_folium import st_folium |
|
|
import plotly.graph_objects as go |
|
|
import plotly.express as px |
|
|
from datetime import datetime, timedelta |
|
|
import requests |
|
|
|
|
|
|
|
|
st.set_page_config( |
|
|
page_title="Charsadda Flood Prediction System", |
|
|
page_icon="🌊", |
|
|
layout="wide", |
|
|
initial_sidebar_state="expanded" |
|
|
) |
|
|
|
|
|
|
|
|
st.markdown("""<style> |
|
|
.main-header { |
|
|
font-size: 2.5rem; |
|
|
font-weight: bold; |
|
|
color: #1f77b4; |
|
|
text-align: center; |
|
|
margin-bottom: 2rem; |
|
|
} |
|
|
.warning-box { |
|
|
background-color: #fff3cd; |
|
|
border-left: 5px solid #ffc107; |
|
|
padding: 1rem; |
|
|
margin: 1rem 0; |
|
|
} |
|
|
.danger-box { |
|
|
background-color: #f8d7da; |
|
|
border-left: 5px solid #dc3545; |
|
|
padding: 1rem; |
|
|
margin: 1rem 0; |
|
|
} |
|
|
.safe-box { |
|
|
background-color: #d4edda; |
|
|
border-left: 5px solid #28a745; |
|
|
padding: 1rem; |
|
|
margin: 1rem 0; |
|
|
} |
|
|
</style>""", unsafe_allow_html=True) |
|
|
|
|
|
|
|
|
@st.cache_resource |
|
|
def load_models(): |
|
|
try: |
|
|
rf_model = joblib.load('random_forest_model.pkl') |
|
|
scaler = joblib.load('scaler.pkl') |
|
|
with open('model_metadata.json', 'r') as f: |
|
|
metadata = json.load(f) |
|
|
return rf_model, scaler, metadata |
|
|
except Exception as e: |
|
|
st.error(f"Error loading models: {e}") |
|
|
return None, None, None |
|
|
|
|
|
rf_model, scaler, metadata = load_models() |
|
|
|
|
|
|
|
|
st.markdown('<div class="main-header">🌊 AI-Powered Flood Prediction System</div>', unsafe_allow_html=True) |
|
|
st.markdown("### Charsadda, Khyber Pakhtunkhwa, Pakistan") |
|
|
|
|
|
|
|
|
with st.sidebar: |
|
|
st.image("https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Flag_of_Pakistan.svg/320px-Flag_of_Pakistan.svg.png", width=150) |
|
|
st.title("Navigation") |
|
|
page = st.radio("Select Page", ["🏠 Home", "🔮 Flood Prediction", "🗺️ Interactive Map", "📊 Model Info", "ℹ️ About"]) |
|
|
st.markdown("---") |
|
|
st.markdown("### Study Area") |
|
|
st.markdown("**Location:** Charsadda District") |
|
|
st.markdown("**Province:** Khyber Pakhtunkhwa") |
|
|
st.markdown("**Coordinates:** 34.15°N, 71.72°E") |
|
|
|
|
|
|
|
|
if page == "🏠 Home": |
|
|
col1, col2 = st.columns(2) |
|
|
with col1: |
|
|
st.markdown("### 📋 Project Overview") |
|
|
st.write("""This AI-powered system predicts flood risks in Charsadda district using: |
|
|
- **Satellite imagery** (Sentinel-1 SAR & Sentinel-2 optical) |
|
|
- **Weather data** (temperature, humidity, rainfall) |
|
|
- **Topographic data** (elevation, slope) |
|
|
- **Machine Learning** (Random Forest, CNN, LSTM models)""") |
|
|
st.markdown("### 🎯 Key Features") |
|
|
st.markdown("""- ✅ Real-time flood risk assessment |
|
|
- ✅ Multi-source data integration |
|
|
- ✅ Interactive flood mapping |
|
|
- ✅ 1-3 day advance predictions |
|
|
- ✅ High-accuracy ML models""") |
|
|
with col2: |
|
|
st.markdown("### 📈 Historical Floods") |
|
|
st.info("""**2022 Flood (August 25-31)**\n- Affected thousands of people\n- Major infrastructure damage\n- Rivers Swat and Kabul overflowed\n\n**2025 Floods (June & August)**\n- Multiple flood events\n- ~35 km² area affected\n- ~41,000 people impacted""") |
|
|
st.markdown("### 🚨 Current Status") |
|
|
st.success("System operational and monitoring ongoing") |
|
|
|
|
|
|
|
|
elif page == "🔮 Flood Prediction": |
|
|
st.markdown("## Flood Risk Prediction") |
|
|
tab1, tab2 = st.tabs(["📤 Upload Data", "⌨️ Manual Input"]) |
|
|
|
|
|
with tab1: |
|
|
st.markdown("### Upload Weather Forecast CSV") |
|
|
st.info("Upload a CSV file with columns: temperature, humidity, rainfall, pressure, wind_speed") |
|
|
uploaded_file = st.file_uploader("Choose a CSV file", type=['csv']) |
|
|
|
|
|
if uploaded_file is not None: |
|
|
df = pd.read_csv(uploaded_file) |
|
|
st.write("**Preview of uploaded data:**") |
|
|
st.dataframe(df.head()) |
|
|
|
|
|
if st.button("Predict Flood Risk", key="predict_upload"): |
|
|
df['VV'] = -10 |
|
|
df['B2'] = 800 |
|
|
df['B3'] = 900 |
|
|
df['B4'] = 600 |
|
|
df['B8'] = 2000 |
|
|
df['B11'] = 1500 |
|
|
df['NDWI'] = 0.0 |
|
|
df['MNDWI'] = 0.0 |
|
|
df['NDVI'] = 0.4 |
|
|
df['elevation'] = 300 |
|
|
df['slope'] = 2 |
|
|
|
|
|
feature_order = metadata['features'] |
|
|
df = df[feature_order] |
|
|
X_scaled = scaler.transform(df) |
|
|
predictions = rf_model.predict(X_scaled) |
|
|
probabilities = rf_model.predict_proba(X_scaled)[:, 1] |
|
|
|
|
|
df['Flood_Risk'] = predictions |
|
|
df['Confidence'] = probabilities * 100 |
|
|
|
|
|
st.markdown("### Prediction Results") |
|
|
flood_count = predictions.sum() |
|
|
col1, col2, col3 = st.columns(3) |
|
|
col1.metric("Total Predictions", len(predictions)) |
|
|
col2.metric("Flood Risk Days", int(flood_count)) |
|
|
col3.metric("Risk Percentage", f"{flood_count/len(predictions)*100:.1f}%") |
|
|
st.dataframe(df[['temperature', 'humidity', 'rainfall', 'Flood_Risk', 'Confidence']]) |
|
|
|
|
|
with tab2: |
|
|
st.markdown("### Manual Weather Input") |
|
|
col1, col2 = st.columns(2) |
|
|
|
|
|
with col1: |
|
|
temperature = st.slider("Temperature (°C)", 15.0, 45.0, 30.0, 0.5) |
|
|
humidity = st.slider("Humidity (%)", 30.0, 100.0, 70.0, 1.0) |
|
|
rainfall = st.slider("Rainfall (mm)", 0.0, 300.0, 50.0, 5.0) |
|
|
with col2: |
|
|
pressure = st.slider("Pressure (hPa)", 950.0, 1050.0, 1010.0, 1.0) |
|
|
wind_speed = st.slider("Wind Speed (m/s)", 0.0, 30.0, 5.0, 0.5) |
|
|
|
|
|
if st.button("Predict Flood Risk", key="predict_manual"): |
|
|
input_data = pd.DataFrame([{ |
|
|
'VV': -10, 'B2': 800, 'B3': 900, 'B4': 600, 'B8': 2000, 'B11': 1500, |
|
|
'NDWI': 0.0, 'MNDWI': 0.0, 'NDVI': 0.4, 'elevation': 300, 'slope': 2, |
|
|
'temperature': temperature, 'humidity': humidity, 'rainfall': rainfall, |
|
|
'pressure': pressure, 'wind_speed': wind_speed |
|
|
}]) |
|
|
|
|
|
input_data = input_data[metadata['features']] |
|
|
X_scaled = scaler.transform(input_data) |
|
|
prediction = rf_model.predict(X_scaled)[0] |
|
|
probability = rf_model.predict_proba(X_scaled)[0, 1] * 100 |
|
|
|
|
|
st.markdown("---") |
|
|
st.markdown("### Prediction Result") |
|
|
|
|
|
if prediction == 1: |
|
|
if probability > 75: |
|
|
st.markdown(f'<div class="danger-box"><h3>🚨 HIGH FLOOD RISK</h3><p>Confidence: {probability:.1f}%</p><p><strong>Action Required:</strong> Immediate evacuation recommended.</p></div>', unsafe_allow_html=True) |
|
|
else: |
|
|
st.markdown(f'<div class="warning-box"><h3>⚠️ MODERATE FLOOD RISK</h3><p>Confidence: {probability:.1f}%</p><p><strong>Action Required:</strong> Stay alert.</p></div>', unsafe_allow_html=True) |
|
|
else: |
|
|
st.markdown(f'<div class="safe-box"><h3>✅ LOW FLOOD RISK</h3><p>Confidence: {100-probability:.1f}%</p><p>Conditions are favorable.</p></div>', unsafe_allow_html=True) |
|
|
|
|
|
fig = go.Figure(go.Indicator( |
|
|
mode="gauge+number", value=probability, title={'text': "Flood Risk Level"}, |
|
|
gauge={'axis': {'range': [0, 100]}, 'bar': {'color': "darkblue"}, |
|
|
'steps': [{'range': [0, 33], 'color': "lightgreen"}, |
|
|
{'range': [33, 66], 'color': "yellow"}, |
|
|
{'range': [66, 100], 'color': "red"}], |
|
|
'threshold': {'line': {'color': "red", 'width': 4}, 'thickness': 0.75, 'value': 50}} |
|
|
)) |
|
|
fig.update_layout(height=300) |
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
|
|
|
elif page == "🗺️ Interactive Map": |
|
|
st.markdown("## Interactive Flood Risk Map") |
|
|
st.info("This map shows the Charsadda study area with historical flood zones.") |
|
|
|
|
|
m = folium.Map(location=[34.15, 71.72], zoom_start=11) |
|
|
boundary_coords = [[34.05, 71.55], [34.05, 71.90], [34.25, 71.90], [34.25, 71.55], [34.05, 71.55]] |
|
|
folium.Polygon(locations=boundary_coords, color='red', weight=3, fill=False, popup='Charsadda Study Area').add_to(m) |
|
|
folium.Marker([34.15, 71.72], popup='Charsadda Center', tooltip='Charsadda District', icon=folium.Icon(color='blue', icon='info-sign')).add_to(m) |
|
|
|
|
|
flood_zones = [([34.10, 71.65], '2022 Flood Zone', 'red'), |
|
|
([34.18, 71.75], '2025 June Flood', 'orange'), |
|
|
([34.12, 71.80], '2025 August Flood', 'darkred')] |
|
|
for coords, name, color in flood_zones: |
|
|
folium.Circle(location=coords, radius=2000, popup=name, color=color, fill=True, fillColor=color, fillOpacity=0.4).add_to(m) |
|
|
|
|
|
st_folium(m, width=1000, height=600) |
|
|
st.markdown("### Map Legend") |
|
|
col1, col2, col3 = st.columns(3) |
|
|
col1.markdown("🔴 **2022 Flood Zone**") |
|
|
col2.markdown("🟠 **2025 June Flood**") |
|
|
col3.markdown("🔴 **2025 August Flood**") |
|
|
|
|
|
|
|
|
elif page == "📊 Model Info": |
|
|
st.markdown("## Model Information") |
|
|
if metadata: |
|
|
col1, col2 = st.columns(2) |
|
|
with col1: |
|
|
st.markdown("### Model Details") |
|
|
st.info(f"""**Best Model:** {metadata['best_model']}\n**Training Date:** {metadata['training_date'][:10]}\n**Features:** {metadata['n_features']}\n**Training Samples:** {metadata['training_samples']:,}\n**Test Samples:** {metadata['test_samples']:,}""") |
|
|
with col2: |
|
|
st.markdown("### Performance Metrics") |
|
|
metrics_df = pd.DataFrame(metadata['performance_metrics']) |
|
|
st.dataframe(metrics_df, use_container_width=True) |
|
|
st.markdown("### Features Used") |
|
|
st.write(metadata['features']) |
|
|
fig = px.bar(metrics_df, x='Model', y=['Accuracy', 'Precision', 'Recall', 'F1-Score', 'ROC-AUC'], barmode='group', title='Model Performance Comparison') |
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
|
|
|
elif page == "ℹ️ About": |
|
|
st.markdown("## About This Project") |
|
|
st.markdown("""### AI-Powered Flood Prediction and Emergency Response System |
|
|
|
|
|
#### Objective |
|
|
To develop an AI-based flood prediction system that provides early warnings and supports efficient coordination of emergency services for Charsadda district, KPK, Pakistan. |
|
|
|
|
|
#### Methodology |
|
|
- **Multi-Source Data Fusion:** Combines Sentinel-1 SAR, Sentinel-2 optical imagery, SRTM elevation data, and weather forecasts |
|
|
- **Machine Learning Models:** Random Forest, CNN, and LSTM models trained on historical flood events (2022 and 2025) |
|
|
- **Real-time Monitoring:** Integration with OpenWeatherMap API for current conditions |
|
|
- **Prediction Timeframe:** 1-3 days advance flood risk assessment |
|
|
|
|
|
#### Data Sources |
|
|
- **Satellite:** Sentinel-1, Sentinel-2 via Google Earth Engine |
|
|
- **Elevation:** SRTM Digital Elevation Model |
|
|
- **Weather:** OpenWeatherMap API |
|
|
- **Historical Events:** 2022 and 2025 flood data |
|
|
|
|
|
#### Technical Stack |
|
|
- **Backend:** Python, scikit-learn, TensorFlow, Google Earth Engine |
|
|
- **Frontend:** Streamlit |
|
|
- **Deployment:** Hugging Face Spaces |
|
|
- **Geospatial:** Folium, Geopandas, GDAL |
|
|
|
|
|
#### Impact |
|
|
- Early warning system for flood-prone communities |
|
|
- Optimized emergency resource allocation |
|
|
- Reduced flood-related casualties and economic losses |
|
|
- Enhanced disaster preparedness and response""") |
|
|
st.markdown("---") |
|
|
st.markdown("### 📧 Contact & Support") |
|
|
st.info("For questions or support, please contact the development team.") |
|
|
|
|
|
|
|
|
st.markdown("---") |
|
|
st.markdown('<div style="text-align: center; color: gray;"><p>© 2025 Charsadda Flood Prediction System | Powered by AI & Satellite Data</p></div>', unsafe_allow_html=True) |
|
|
|