FireSight / app.py
Navya-Sree's picture
Update app.py
e57d91d verified
Raw
History Blame Contribute Delete
11 kB
import os
import sys
import pandas as pd
import numpy as np
import gradio as gr
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler
import tempfile
import json
import matplotlib.pyplot as plt
import io
import base64
import shutil
from datetime import datetime
# Configure base directory
BASE_OUTPUT_DIR = "firesight_output"
os.makedirs(BASE_OUTPUT_DIR, exist_ok=True)
class EnhancedDataProcessor:
"""Advanced data processing with spatial features"""
def __init__(self, output_dir):
self.output_dir = output_dir
os.makedirs(os.path.join(output_dir, "maps"), exist_ok=True)
os.makedirs(os.path.join(output_dir, "reports"), exist_ok=True)
self.usa_bbox = {
'min_lat': 24.396308,
'max_lat': 49.384358,
'min_lon': -125.000000,
'max_lon': -66.934570
}
def process_all_data(self, hotspots_df, weather_data, sensor_data):
"""Process and integrate all data sources"""
# Data validation and cleaning
processed_data = self._validate_inputs(hotspots_df, weather_data, sensor_data)
# Feature engineering
processed_data = self._create_spatial_features(processed_data)
processed_data = self._calculate_risk_index(processed_data)
# Generate USA map visualization
self._create_usa_map(processed_data)
return processed_data
def _validate_inputs(self, hotspots, weather, sensors):
"""Validate and clean input data"""
dfs = []
if not hotspots.empty:
hotspots['acq_datetime'] = pd.to_datetime(
hotspots['acq_date'] + ' ' + hotspots['acq_time'].astype(str).str.zfill(4),
errors='coerce'
)
hotspots = self._filter_within_usa(hotspots)
dfs.append(hotspots)
if weather:
weather_df = pd.DataFrame(weather)
weather_df = self._convert_weather_units(weather_df)
weather_df = self._filter_within_usa(weather_df)
dfs.append(weather_df)
if not sensors.empty:
sensors = self._filter_within_usa(sensors)
sensors['fuel_moisture_risk'] = 1 - (sensors['fuel_moisture_pct'] / 100)
dfs.append(sensors)
return pd.concat(dfs, ignore_index=True) if dfs else pd.DataFrame()
def _filter_within_usa(self, df):
"""Filter coordinates to USA bounding box"""
return df[
(df['latitude'].between(self.usa_bbox['min_lat'], self.usa_bbox['max_lat'])) &
(df['longitude'].between(self.usa_bbox['min_lon'], self.usa_bbox['max_lon']))
].copy()
def _create_spatial_features(self, df):
"""Create spatial clustering features"""
if not df.empty:
# DBSCAN clustering
coords = df[['latitude', 'longitude']].values
dbscan = DBSCAN(eps=0.3, min_samples=5).fit(coords)
df['cluster'] = dbscan.labels_
# Cluster-based features
cluster_stats = df.groupby('cluster').agg({
'frp': ['mean', 'max'],
'confidence': 'mean',
'latitude': 'count'
}).reset_index()
cluster_stats.columns = ['cluster', 'frp_mean', 'frp_max', 'confidence_mean', 'cluster_size']
df = df.merge(cluster_stats, on='cluster', how='left')
return df
def _convert_weather_units(self, df):
"""Standardize weather measurements"""
if 'temperature' in df.columns:
df['temperature_c'] = np.where(
df['temperature_unit'] == 'F',
(df['temperature'] - 32) * 5/9,
df['temperature']
)
if 'wind_speed' in df.columns:
df['wind_speed_ms'] = df['wind_speed'].str.extract('(\d+)').astype(float)
df['wind_speed_ms'] = np.where(
df['wind_speed'].str.contains('mph'),
df['wind_speed_ms'] * 0.44704,
df['wind_speed_ms']
)
return df
def _calculate_risk_index(self, df, weights=None):
"""Dynamic risk calculation with customizable weights"""
if df.empty:
return df
features = ['frp_mean', 'confidence_mean', 'temperature_c',
'wind_speed_ms', 'fuel_moisture_risk']
# Handle missing features
available_features = [f for f in features if f in df.columns]
if not available_features:
return df
# Default weights if not provided
weights = weights or [0.3, 0.2, 0.2, 0.2, 0.1][:len(available_features)]
weights = np.array(weights) / sum(weights) # Normalize
# Standardize features
scaler = StandardScaler()
scaled = scaler.fit_transform(df[available_features].fillna(0))
# Store scaled features for dynamic recalculation
for i, feat in enumerate(available_features):
df[f'scaled_{feat}'] = scaled[:, i]
# Calculate risk index
df['composite_risk_index'] = np.dot(scaled, weights)
df['composite_risk_index'] = 100 * (df['composite_risk_index'] - df['composite_risk_index'].min()) / \
(df['composite_risk_index'].max() - df['composite_risk_index'].min())
return df
def _create_usa_map(self, df):
"""Generate interactive USA risk map"""
if df.empty or 'composite_risk_index' not in df.columns:
return
fig = px.scatter_mapbox(
df,
lat='latitude',
lon='longitude',
color='composite_risk_index',
color_continuous_scale='Viridis',
zoom=3,
center={"lat": 37.0902, "lon": -95.7129},
mapbox_style="open-street-map",
title='Wildfire Risk Map - USA',
hover_data=['composite_risk_index', 'temperature_c', 'wind_speed_ms']
)
fig.update_layout(margin={"r": 0, "t": 40, "l": 0, "b": 0})
map_path = os.path.join(self.output_dir, "maps", "fire_risk_map.html")
fig.write_html(map_path)
def create_advanced_interface():
"""Create Gradio interface with advanced features"""
with gr.Blocks(title="FireSight Pro: Advanced Wildfire Analysis") as demo:
gr.Markdown("""
# 🔥 FireSight Pro: Advanced Wildfire Risk Analysis
**Integrated USA Map | Dynamic Risk Modeling | Real-time Analytics**
""")
with gr.Tab("Data Hub"):
with gr.Row():
with gr.Column(scale=2):
gr.Markdown("### Multi-Source Data Integration")
hotspots = gr.File(label="Satellite Hotspots")
weather = gr.File(label="Weather Data Stream")
sensors = gr.File(label="IoT Sensor Network")
gr.Markdown("### Live Data Controls")
with gr.Row():
sample_btn = gr.Button("Generate Live Sample", variant="secondary")
process_btn = gr.Button("Launch Analysis", variant="primary")
with gr.Column(scale=1):
gr.Markdown("### Real-Time Data Monitor")
data_stats = gr.JSON(label="Ingestion Metrics")
proc_status = gr.Textbox(label="Processing Status")
with gr.Tab("Risk Navigator"):
with gr.Row():
with gr.Column(scale=3):
gr.Markdown("### Live Risk Atlas")
risk_map = gr.HTML(label="USA Risk Map")
with gr.Column(scale=1):
gr.Markdown("### Risk Parameters")
risk_weights = [
gr.Slider(0, 1, 0.3, label="Thermal Activity"),
gr.Slider(0, 1, 0.2, label="Confidence Level"),
gr.Slider(0, 1, 0.2, label="Temperature Index"),
gr.Slider(0, 1, 0.2, label="Wind Impact"),
gr.Slider(0, 1, 0.1, label="Fuel Dryness")
]
update_btn = gr.Button("Dynamic Update", variant="primary")
with gr.Tab("Analytics Console"):
with gr.Row():
with gr.Column():
gr.Markdown("### Risk Distribution Matrix")
risk_plot = gr.Plot()
with gr.Column():
gr.Markdown("### Correlation Analyzer")
corr_matrix = gr.Plot()
# Event handlers
process_btn.click(
fn=process_data_flow,
inputs=[hotspots, weather, sensors],
outputs=[data_stats, proc_status]
)
update_btn.click(
fn=update_risk_model,
inputs=risk_weights,
outputs=[risk_map, risk_plot, corr_matrix]
)
return demo
def process_data_flow(hotspots, weather, sensors):
"""Simplified data processing flow for demo"""
processor = EnhancedDataProcessor(BASE_OUTPUT_DIR)
# Sample data generation
hotspots_df = pd.read_csv(hotspots.name) if hotspots else generate_sample_hotspots()
weather_data = pd.read_csv(weather.name).to_dict('records') if weather else generate_sample_weather()
sensors_df = pd.read_csv(sensors.name) if sensors else generate_sample_sensors()
processed_data = processor.process_all_data(hotspots_df, weather_data, sensors_df)
stats = {
"hotspots": len(hotspots_df),
"weather_points": len(weather_data),
"sensors": len(sensors_df),
"risk_zones": len(processed_data)
}
return stats, "Analysis complete. Risk map updated."
def update_risk_model(*weights):
"""Dynamic risk model update"""
processor = EnhancedDataProcessor(BASE_OUTPUT_DIR)
processed_data = load_processed_data()
if not processed_data.empty:
processed_data = processor._calculate_risk_index(processed_data, weights)
fig = create_risk_visualizations(processed_data)
return fig, create_distribution_plot(processed_data), create_correlation_plot(processed_data)
return None, None, None
def create_risk_visualizations(df):
"""Generate updated visualizations"""
fig = px.scatter_mapbox(
df,
lat='latitude',
lon='longitude',
color='composite_risk_index',
color_continuous_scale='Viridis',
zoom=3,
center={"lat": 37.0902, "lon": -95.7129},
mapbox_style="open-street-map"
)
return fig.to_html()
if __name__ == "__main__":
app = create_advanced_interface()
app.launch(server_name="0.0.0.0", server_port=7860)