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)