Spaces:
Build error
Build error
| 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) |