Ans / app.py
anasfsd123's picture
Create app.py
6180f49 verified
import streamlit as st
import requests
from datetime import datetime, timedelta
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
import os
import folium
from streamlit_folium import st_folium
import json
import time
from geopy.geocoders import Nominatim
from geopy.distance import geodesic
import warnings
warnings.filterwarnings('ignore')
# Enhanced Emergency AI System - NEW FEATURES
class EmergencyAI:
def __init__(self):
self.disaster_log = []
self.rescue_teams = []
self.languages = {
'en': 'English', 'es': 'Spanish', 'fr': 'French', 'de': 'German',
'it': 'Italian', 'pt': 'Portuguese', 'ar': 'Arabic', 'ur': 'Urdu',
'hi': 'Hindi', 'zh': 'Chinese', 'ja': 'Japanese', 'ko': 'Korean',
'ru': 'Russian', 'tr': 'Turkish'
}
def get_first_aid_instructions(self, emergency_type, severity="moderate"):
"""Provide instant first aid instructions based on emergency type"""
instructions = {
'earthquake': {
'immediate': {
'high': [
"🚨 IMMEDIATE ACTIONS:",
"1. DROP to hands and knees immediately",
"2. COVER your head and neck under a desk/table",
"3. HOLD ON to your shelter and protect yourself",
"4. Stay where you are until shaking stops",
"5. Do NOT run outside during shaking"
],
'moderate': [
"⚠️ SAFETY ACTIONS:",
"1. Move away from windows and heavy objects",
"2. Take cover under sturdy furniture",
"3. Protect your head and neck",
"4. Wait for shaking to stop completely"
],
'low': [
"ℹ️ PRECAUTIONARY ACTIONS:",
"1. Stay calm and aware of your surroundings",
"2. Identify safe spaces in your location",
"3. Check for any structural damage",
"4. Be prepared for possible aftershocks"
]
},
'after': [
"🏥 POST-EARTHQUAKE CARE:",
"1. Check for injuries - provide first aid if trained",
"2. Check for gas leaks, electrical damage, structural damage",
"3. Use flashlight, not candles or matches",
"4. Stay out of damaged buildings",
"5. Listen to emergency broadcasts",
"6. Be prepared for aftershocks",
"7. Help others if you can do so safely"
]
},
'flood': {
'immediate': {
'high': [
"🌊 FLOOD EMERGENCY:",
"1. Get to higher ground IMMEDIATELY",
"2. Avoid walking in moving water (6+ inches can knock you down)",
"3. Don't drive through flooded roads",
"4. If trapped in building, go to highest floor",
"5. Signal for help from roof/upper floor"
],
'moderate': [
"⚠️ FLOOD PRECAUTIONS:",
"1. Move to higher ground if possible",
"2. Avoid flood waters",
"3. Monitor emergency broadcasts",
"4. Prepare emergency supplies"
],
'low': [
"ℹ️ FLOOD AWARENESS:",
"1. Monitor water levels",
"2. Prepare evacuation plan",
"3. Move valuables to higher ground",
"4. Stay informed of conditions"
]
}
},
'injury': {
'bleeding': [
"🩸 BLEEDING CONTROL:",
"1. Apply direct pressure with clean cloth",
"2. Elevate injured area above heart if possible",
"3. Don't remove objects embedded in wounds",
"4. Apply pressure to pressure points if bleeding severe",
"5. Seek medical help immediately for severe bleeding"
],
'fracture': [
"🦴 FRACTURE CARE:",
"1. Don't move the person unless in immediate danger",
"2. Immobilize the injured area",
"3. Apply ice wrapped in cloth (not directly on skin)",
"4. Check circulation below injury site",
"5. Get emergency medical help"
],
'unconscious': [
"😵 UNCONSCIOUS PERSON:",
"1. Check for responsiveness (tap shoulders, shout)",
"2. Check for breathing and pulse",
"3. If breathing: place in recovery position",
"4. If not breathing: start CPR if trained",
"5. Call emergency services immediately"
]
}
}
return instructions.get(emergency_type, {}).get('immediate', {}).get(severity,
instructions.get(emergency_type, {}).get('immediate', {}).get('moderate',
["No specific instructions available for this emergency type."]))
def coordinate_rescue_teams(self, emergency_location, emergency_type, severity):
"""Coordinate rescue teams and resources"""
coordination_plan = {
'priority_level': self._get_priority_level(severity),
'required_teams': self._get_required_teams(emergency_type, severity),
'resource_allocation': self._get_resource_allocation(emergency_type),
'evacuation_zones': self._calculate_evacuation_zones(emergency_location, severity),
'communication_protocol': self._get_communication_protocol(severity)
}
return coordination_plan
def _get_priority_level(self, severity):
priority_map = {'low': 'P3 - Standard', 'moderate': 'P2 - Urgent', 'high': 'P1 - Critical', 'extreme': 'P0 - Immediate'}
return priority_map.get(severity, 'P2 - Urgent')
def _get_required_teams(self, emergency_type, severity):
base_teams = ['Emergency Medical Services', 'Fire Department', 'Police']
if emergency_type == 'earthquake':
base_teams.extend(['Search and Rescue', 'Structural Engineers', 'Utility Teams'])
if severity in ['high', 'extreme']:
base_teams.extend(['Heavy Rescue', 'Disaster Relief', 'Military Support'])
elif emergency_type == 'flood':
base_teams.extend(['Water Rescue', 'Coast Guard', 'Emergency Shelters'])
return base_teams
def _get_resource_allocation(self, emergency_type):
resources = {
'earthquake': ['Medical Supplies', 'Heavy Machinery', 'Communication Equipment', 'Emergency Shelters', 'Food & Water'],
'flood': ['Boats/Rafts', 'Water Pumps', 'Sandbags', 'Medical Supplies', 'Emergency Shelters'],
'general': ['First Aid Supplies', 'Communication Equipment', 'Transportation', 'Emergency Power']
}
return resources.get(emergency_type, resources['general'])
def _calculate_evacuation_zones(self, location, severity):
radius_map = {'low': 1, 'moderate': 3, 'high': 10, 'extreme': 25}
radius = radius_map.get(severity, 3)
return {
'immediate_evacuation': f"{radius/2} km radius",
'precautionary_evacuation': f"{radius} km radius",
'shelter_locations': "Community centers, schools, hospitals outside danger zone",
'evacuation_routes': "Main roads leading away from epicenter/danger zone"
}
def _get_communication_protocol(self, severity):
if severity in ['high', 'extreme']:
return {
'frequency': 'Every 15 minutes',
'channels': ['Emergency Radio', 'Cell Broadcast', 'Social Media', 'TV/Radio'],
'languages': 'Multi-language broadcasts required',
'backup_systems': 'Satellite communication activated'
}
else:
return {
'frequency': 'Every hour',
'channels': ['Emergency Radio', 'Official websites'],
'languages': 'Local language primary',
'backup_systems': 'Standard communication systems'
}
def translate_emergency_message(self, message, target_language='en'):
"""Translate emergency messages - in real implementation would use translation API"""
# This is a simplified version - in production, you'd integrate with Google Translate API or similar
translations = {
'earthquake_alert': {
'en': 'EARTHQUAKE ALERT: Take cover immediately!',
'es': 'ALERTA DE TERREMOTO: ¡Busque refugio inmediatamente!',
'fr': 'ALERTE AU TREMBLEMENT DE TERRE: Mettez-vous à l\'abri immédiatement!',
'de': 'ERDBEBENALARM: Sofort Schutz suchen!',
'ur': 'زلزلے کا الرٹ: فوری طور پر محفوظ جگہ تلاش کریں!',
'ar': 'تنبيه زلزال: ابحث عن مأوى فوراً!',
'zh': '地震警报:立即寻找掩护!',
'ja': '地震警報:直ちに避難してください!'
},
'evacuation_order': {
'en': 'EVACUATION ORDER: Leave the area immediately via designated routes.',
'es': 'ORDEN DE EVACUACIÓN: Abandone el área inmediatamente por las rutas designadas.',
'fr': 'ORDRE D\'ÉVACUATION: Quittez la zone immédiatement par les routes désignées.',
'de': 'EVAKUIERUNGSBEFEHL: Verlassen Sie das Gebiet sofort über die vorgesehenen Routen.',
'ur': 'انخلاء کا حکم: مقررہ راستوں سے فوری طور پر علاقہ چھوڑیں۔',
'ar': 'أمر إخلاء: اتركوا المنطقة فوراً عبر الطرق المحددة.',
'zh': '疏散令:立即通过指定路线离开该地区。',
'ja': '避難命令:指定されたルートで直ちにその地域から避難してください。'
}
}
# In production, this would make an API call to a translation service
return translations.get(message.lower().replace(' ', '_'), {}).get(target_language,
f"Translation not available for {target_language}")
def learn_from_disaster(self, disaster_data):
"""Learn from each disaster to improve future responses"""
learning_points = {
'response_time': disaster_data.get('response_time', 0),
'effectiveness': disaster_data.get('effectiveness_rating', 0),
'casualties': disaster_data.get('casualties', 0),
'lessons_learned': disaster_data.get('lessons', []),
'improvements_needed': []
}
# Analyze patterns and suggest improvements
if learning_points['response_time'] > 600: # 10 minutes
learning_points['improvements_needed'].append("Improve emergency alert systems")
if learning_points['effectiveness'] < 7: # out of 10
learning_points['improvements_needed'].append("Enhanced training for emergency teams")
self.disaster_log.append({
'timestamp': datetime.now(),
'data': disaster_data,
'learning_points': learning_points
})
return learning_points
# Initialize Emergency AI
emergency_ai = EmergencyAI()
# Secure API key handling
def get_groq_api_key():
"""Securely get GROQ API key from environment variables or Streamlit secrets"""
try:
return st.secrets["GROQ_API_KEY"]
except:
api_key = os.getenv("GROQ_API_KEY")
if not api_key:
st.error("🔐 GROQ API key not found. Please configure it in Streamlit secrets or environment variables.")
st.info("""
**To configure the API key:**
1. **For Hugging Face Spaces**: Add `GROQ_API_KEY` in your Space settings under 'Repository secrets'
2. **For local development**: Set environment variable `GROQ_API_KEY=your_key_here`
3. **For Streamlit Cloud**: Add to secrets.toml file
""")
return None
return api_key
# Color schemes for different magnitude levels
MAGNITUDE_COLORS = {
'Low': '#00ff00', # Green
'Moderate': '#ffff00', # Yellow
'High': '#ff8000', # Orange
'Severe': '#ff0000', # Red
'Extreme': '#800000' # Dark Red
}
# Risk assessment thresholds
RISK_THRESHOLDS = {
'low': {'count': 5, 'max_magnitude': 3.0},
'moderate': {'count': 10, 'max_magnitude': 4.5},
'high': {'count': 20, 'max_magnitude': 5.5},
'severe': {'count': 30, 'max_magnitude': 6.5},
'extreme': {'count': 50, 'max_magnitude': 7.0}
}
# Emergency protocols
EMERGENCY_PROTOCOLS = {
'low': "Monitor situation. No immediate action required.",
'moderate': "Stay alert. Review emergency plans.",
'high': "Prepare emergency kit. Stay informed.",
'severe': "Follow evacuation orders if issued. Seek shelter.",
'extreme': "IMMEDIATE EVACUATION. Follow emergency services."
}
def get_groq_summary(prompt, context=""):
"""Enhanced Groq LLM function with secure API key handling"""
api_key = get_groq_api_key()
if not api_key:
return "AI Analysis unavailable - API key not configured"
try:
from groq import Groq
client = Groq(api_key=api_key)
full_prompt = f"{context}\n\n{prompt}" if context else prompt
response = client.chat.completions.create(
model="llama-3.3-70b-versatile",
messages=[
{"role": "system", "content": "You are an expert emergency response AI, seismologist, and disaster management specialist. Provide detailed, accurate, and actionable information with focus on safety and emergency preparedness."},
{"role": "user", "content": full_prompt}
],
max_tokens=2048,
temperature=0.7,
top_p=0.9,
presence_penalty=0.1,
frequency_penalty=0.1
)
return response.choices[0].message.content
except ImportError:
return "AI Analysis unavailable - Groq library not installed"
except Exception as e:
return f"AI Analysis Error: {str(e)}"
def fetch_earthquakes(min_magnitude=2.5, hours=24, region_bbox=None, detailed=True):
"""Fetch earthquake data with enhanced error handling and data processing"""
try:
endtime = datetime.utcnow()
starttime = endtime - timedelta(hours=hours)
url = "https://earthquake.usgs.gov/fdsnws/event/1/query"
params = {
"format": "geojson",
"starttime": starttime.strftime('%Y-%m-%dT%H:%M:%S'),
"endtime": endtime.strftime('%Y-%m-%dT%H:%M:%S'),
"minmagnitude": min_magnitude,
"orderby": "time",
"limit": 500 if detailed else 200
}
if region_bbox:
params.update({
"minlatitude": region_bbox[1],
"maxlatitude": region_bbox[3],
"minlongitude": region_bbox[0],
"maxlongitude": region_bbox[2],
})
response = requests.get(url, params=params, timeout=30)
response.raise_for_status()
data = response.json()
features = data.get('features', [])
earthquakes = []
for f in features:
prop = f['properties']
geom = f['geometry']
earthquake = {
'time': datetime.utcfromtimestamp(prop['time']/1000),
'place': prop['place'],
'magnitude': prop['mag'],
'longitude': geom['coordinates'][0],
'latitude': geom['coordinates'][1],
'depth': geom['coordinates'][2],
'url': prop['url'],
'type': prop.get('type', 'earthquake'),
'status': prop.get('status', 'automatic'),
'tsunami': prop.get('tsunami', 0),
'felt': prop.get('felt', 0),
'cdi': prop.get('cdi', 0),
'mmi': prop.get('mmi', 0),
'alert': prop.get('alert', ''),
'sig': prop.get('sig', 0)
}
earthquake['risk_level'] = calculate_risk_level(earthquake['magnitude'])
earthquake['time_ago'] = calculate_time_ago(earthquake['time'])
earthquakes.append(earthquake)
df = pd.DataFrame(earthquakes)
if not df.empty:
df['magnitude_category'] = df['magnitude'].apply(categorize_magnitude)
df['depth_category'] = df['depth'].apply(categorize_depth)
df['hour_of_day'] = df['time'].dt.hour
df['day_of_week'] = df['time'].dt.day_name()
return df
except requests.exceptions.RequestException as e:
st.error(f"Network error: {e}")
return pd.DataFrame()
except Exception as e:
st.error(f"Data processing error: {e}")
return pd.DataFrame()
def calculate_risk_level(magnitude):
"""Calculate risk level based on magnitude"""
if magnitude >= 7.0:
return 'extreme'
elif magnitude >= 6.0:
return 'severe'
elif magnitude >= 5.0:
return 'high'
elif magnitude >= 4.0:
return 'moderate'
else:
return 'low'
def categorize_magnitude(magnitude):
"""Categorize magnitude for analysis"""
if magnitude >= 7.0:
return 'Major (≥7.0)'
elif magnitude >= 6.0:
return 'Strong (6.0-6.9)'
elif magnitude >= 5.0:
return 'Moderate (5.0-5.9)'
elif magnitude >= 4.0:
return 'Light (4.0-4.9)'
else:
return 'Minor (<4.0)'
def categorize_depth(depth):
"""Categorize depth for analysis"""
if depth < 70:
return 'Shallow (<70km)'
elif depth < 300:
return 'Intermediate (70-300km)'
else:
return 'Deep (>300km)'
def calculate_time_ago(time):
"""Calculate time ago in human readable format"""
now = datetime.utcnow()
diff = now - time
if diff.days > 0:
return f"{diff.days} day(s) ago"
elif diff.seconds >= 3600:
hours = diff.seconds // 3600
return f"{hours} hour(s) ago"
elif diff.seconds >= 60:
minutes = diff.seconds // 60
return f"{minutes} minute(s) ago"
else:
return "Just now"
def analyze_seismic_patterns(df):
"""Analyze seismic patterns and trends"""
if df.empty:
return {}
analysis = {}
try:
if len(df) > 0:
analysis['hourly_distribution'] = df['hour_of_day'].value_counts().sort_index()
analysis['daily_distribution'] = df['day_of_week'].value_counts()
if 'magnitude' in df.columns and len(df) > 0:
analysis['magnitude_stats'] = {
'mean': df['magnitude'].mean(),
'median': df['magnitude'].median(),
'std': df['magnitude'].std(),
'max': df['magnitude'].max(),
'min': df['magnitude'].min()
}
if 'depth' in df.columns and len(df) > 0:
analysis['depth_stats'] = {
'mean': df['depth'].mean(),
'median': df['depth'].median(),
'std': df['depth'].std()
}
if 'risk_level' in df.columns and len(df) > 0:
analysis['risk_distribution'] = df['risk_level'].value_counts()
if len(df) > 1 and 'latitude' in df.columns and 'longitude' in df.columns:
analysis['geographic_center'] = {
'lat': df['latitude'].mean(),
'lon': df['longitude'].mean()
}
except Exception as e:
st.warning(f"Error in pattern analysis: {str(e)}")
return {}
return analysis
def calculate_overall_risk(df):
"""Calculate overall risk assessment"""
if df.empty:
return 'low', "No recent seismic activity"
count = len(df)
max_magnitude = df['magnitude'].max()
risk_score = 0
if count >= RISK_THRESHOLDS['extreme']['count']:
risk_score += 40
elif count >= RISK_THRESHOLDS['severe']['count']:
risk_score += 30
elif count >= RISK_THRESHOLDS['high']['count']:
risk_score += 20
elif count >= RISK_THRESHOLDS['moderate']['count']:
risk_score += 10
if max_magnitude >= RISK_THRESHOLDS['extreme']['max_magnitude']:
risk_score += 40
elif max_magnitude >= RISK_THRESHOLDS['severe']['max_magnitude']:
risk_score += 30
elif max_magnitude >= RISK_THRESHOLDS['high']['max_magnitude']:
risk_score += 20
elif max_magnitude >= RISK_THRESHOLDS['moderate']['max_magnitude']:
risk_score += 10
if risk_score >= 60:
risk_level = 'extreme'
elif risk_score >= 40:
risk_level = 'severe'
elif risk_score >= 25:
risk_level = 'high'
elif risk_score >= 10:
risk_level = 'moderate'
else:
risk_level = 'low'
return risk_level, f"Risk Score: {risk_score}/80"
def create_advanced_map(df, region_bbox=None):
"""Create an advanced interactive map"""
if df.empty:
return None
center_lat = df['latitude'].mean()
center_lon = df['longitude'].mean()
m = folium.Map(
location=[center_lat, center_lon],
zoom_start=6,
tiles='OpenStreetMap'
)
for idx, row in df.iterrows():
if row['magnitude'] >= 6.0:
color = 'red'
radius = 15
elif row['magnitude'] >= 5.0:
color = 'orange'
radius = 12
elif row['magnitude'] >= 4.0:
color = 'yellow'
radius = 10
else:
color = 'green'
radius = 8
popup_content = f"""
<b>Magnitude {row['magnitude']}</b><br>
Location: {row['place']}<br>
Time: {row['time'].strftime('%Y-%m-%d %H:%M:%S')}<br>
Depth: {row['depth']:.1f} km<br>
Risk Level: {row['risk_level'].upper()}<br>
<a href="{row['url']}" target="_blank">USGS Details</a>
"""
folium.CircleMarker(
location=[row['latitude'], row['longitude']],
radius=radius,
popup=popup_content,
color=color,
fill=True,
fillOpacity=0.7
).add_to(m)
if region_bbox:
folium.Rectangle(
bounds=[[region_bbox[1], region_bbox[0]], [region_bbox[3], region_bbox[2]]],
color='blue',
weight=2,
fillOpacity=0.1
).add_to(m)
return m
def create_comprehensive_charts(df, analysis):
"""Create comprehensive visualization charts"""
if df.empty:
return []
charts = []
# Magnitude over time with trend - with error handling
fig1 = go.Figure()
fig1.add_trace(go.Scatter(
x=df['time'], y=df['magnitude'],
mode='markers',
marker=dict(
size=df['magnitude'] * 2,
color=df['magnitude'],
colorscale='Reds',
showscale=True
),
name='Earthquakes'
))
# Only add trend line if we have enough data points (at least 2)
if len(df) >= 2:
try:
z = np.polyfit(range(len(df)), df['magnitude'], 1)
p = np.poly1d(z)
fig1.add_trace(go.Scatter(
x=df['time'], y=p(range(len(df))),
mode='lines',
name='Trend',
line=dict(color='blue', dash='dash')
))
except (np.linalg.LinAlgError, ValueError) as e:
st.warning(f"Trend analysis unavailable: {str(e)}")
fig1.update_layout(
title='Earthquake Magnitude Over Time with Trend',
xaxis_title='Time',
yaxis_title='Magnitude',
height=400
)
charts.append(fig1)
# Magnitude distribution histogram - only if we have data
if len(df) > 0:
fig2 = px.histogram(
df, x='magnitude', nbins=min(20, len(df)),
title='Magnitude Distribution',
labels={'magnitude': 'Magnitude', 'count': 'Frequency'}
)
fig2.update_layout(height=400)
charts.append(fig2)
# Depth vs Magnitude scatter - only if we have data
if len(df) > 0:
fig3 = px.scatter(
df, x='depth', y='magnitude', color='magnitude',
title='Depth vs Magnitude Relationship',
labels={'depth': 'Depth (km)', 'magnitude': 'Magnitude'}
)
fig3.update_layout(height=400)
charts.append(fig3)
# Hourly distribution - only if we have the data
if 'hourly_distribution' in analysis and len(analysis['hourly_distribution']) > 0:
fig4 = px.bar(
x=analysis['hourly_distribution'].index,
y=analysis['hourly_distribution'].values,
title='Earthquake Activity by Hour of Day',
labels={'x': 'Hour', 'y': 'Count'}
)
fig4.update_layout(height=400)
charts.append(fig4)
# Risk level distribution - only if we have the data
if 'risk_distribution' in analysis and len(analysis['risk_distribution']) > 0:
fig5 = px.pie(
values=analysis['risk_distribution'].values,
names=analysis['risk_distribution'].index,
title='Risk Level Distribution'
)
fig5.update_layout(height=400)
charts.append(fig5)
return charts
def main():
st.set_page_config(
page_title="🌍 QuakeGuard AI - Emergency Response System",
page_icon="🌍",
layout="wide",
initial_sidebar_state="expanded"
)
st.markdown("""
<style>
.main-header {
font-size: 3rem;
font-weight: bold;
text-align: center;
color: #1f77b4;
margin-bottom: 2rem;
}
.risk-extreme { color: #800000; font-weight: bold; font-size: 1.2rem; }
.risk-severe { color: #ff0000; font-weight: bold; font-size: 1.1rem; }
.risk-high { color: #ff8000; font-weight: bold; }
.risk-moderate { color: #ffaa00; font-weight: bold; }
.risk-low { color: #44aa44; font-weight: bold; }
.metric-card {
background-color: #f0f2f6;
padding: 1rem;
border-radius: 0.5rem;
border-left: 4px solid #1f77b4;
color: #222 !important;
}
.emergency-card {
background-color: #ffe6e6;
padding: 1rem;
border-radius: 0.5rem;
border-left: 4px solid #ff0000;
color: #222 !important;
}
.first-aid-card {
background-color: #e6f3ff;
padding: 1rem;
border-radius: 0.5rem;
border-left: 4px solid #0066cc;
color: #222 !important;
}
</style>
""", unsafe_allow_html=True)
st.markdown('<h1 class="main-header">🌍 Emergency AI Response System</h1>', unsafe_allow_html=True)
st.markdown("### Real-time disaster monitoring with AI-powered emergency response, first aid, rescue coordination & multilingual support")
# Check if API key is configured
if not get_groq_api_key():
st.stop()
# Enhanced sidebar with new emergency features
st.sidebar.header("⚙️ Configuration")
# Emergency AI Settings
st.sidebar.subheader("🚨 Emergency AI Settings")
emergency_language = st.sidebar.selectbox(
"🌐 Emergency Language",
options=list(emergency_ai.languages.keys()),
format_func=lambda x: emergency_ai.languages[x],
index=0
)
show_first_aid = st.sidebar.checkbox("🏥 First Aid Instructions", value=True)
show_rescue_coordination = st.sidebar.checkbox("🚁 Rescue Coordination", value=True)
show_multilingual = st.sidebar.checkbox("🗣️ Multilingual Support", value=True)
show_disaster_learning = st.sidebar.checkbox("🧠 Disaster Learning", value=True)
region = st.sidebar.text_input(
"🌍 Region (optional)",
placeholder="e.g., California, Pakistan, Japan"
)
col1, col2 = st.sidebar.columns(2)
with col1:
min_magnitude = st.slider("📏 Min Magnitude", 1.0, 7.0, 2.5, 0.1)
with col2:
hours = st.slider("⏰ Hours", 1, 168, 24)
with st.sidebar.expander("🔧 Advanced Options"):
show_detailed_analysis = st.checkbox("Detailed Analysis", value=True)
show_ai_summary = st.checkbox("AI Summary", value=True)
show_emergency_protocols = st.checkbox("Emergency Protocols", value=True)
region_bboxes = {
"California": [-125, 32, -114, 42],
"Pakistan": [60, 23, 77, 37],
"Japan": [129, 31, 146, 45],
"Chile": [-75, -56, -66, -17],
"Turkey": [25, 36, 45, 43],
"Indonesia": [95, -11, 141, 6],
"India": [68, 6, 97, 37],
"Mexico": [-118, 14, -86, 33],
"USA": [-125, 24, -66, 49],
"World": [-180, -90, 180, 90]
}
region_bbox = region_bboxes.get(region.strip().title()) if region else None
if st.button("🔄 Refresh Data", type="primary"):
st.rerun()
with st.spinner("🌐 Fetching earthquake data..."):
df = fetch_earthquakes(min_magnitude, hours, region_bbox, show_detailed_analysis)
if df.empty:
st.warning("⚠️ No recent earthquakes found matching your criteria.")
st.info("💡 Try reducing the minimum magnitude or increasing the time range.")
# Show emergency features even when no data
if show_first_aid:
st.markdown("""
<div class="first-aid-card">
<h3>🏥 Emergency First Aid - Ready Mode</h3>
<p>First aid instructions available for:</p>
<ul>
<li>🌍 Earthquake injuries</li>
<li>🌊 Flood emergencies</li>
<li>🩸 Bleeding control</li>
<li>🦴 Fracture management</li>
<li>😵 Unconscious victims</li>
</ul>
<p><strong>Emergency activated instructions will appear when seismic activity is detected.</strong></p>
</div>
""", unsafe_allow_html=True)
# Show a simple message when no data is available
st.markdown("""
<div class="metric-card">
<h3>🚨 Current Risk Level: <span class="risk-low">LOW</span></h3>
<p><strong>Risk Score:</strong> 0/80</p>
<p><strong>Emergency Protocol:</strong> Monitor situation. No immediate action required.</p>
</div>
""", unsafe_allow_html=True)
# Show tabs with appropriate messages
tab1, tab2, tab3, tab4, tab5, tab6 = st.tabs(["🗺️ Map", "📊 Analytics", "📋 Data", "🤖 AI Analysis", "🚨 Emergency", "🏥 Emergency AI"])
with tab1:
st.subheader("🌍 Interactive Earthquake Map")
st.info("No earthquake data available for map visualization")
with tab2:
st.subheader("📊 Advanced Analytics")
st.info("No earthquake data available for analysis")
with tab3:
st.subheader("📋 Earthquake Data")
st.info("No earthquake data available")
with tab4:
st.subheader("🤖 AI-Powered Analysis")
if show_ai_summary:
st.info("No earthquake data available for AI analysis")
else:
st.info("Enable AI Summary in Advanced Options to see AI analysis.")
with tab5:
st.subheader("🚨 Emergency Information")
if show_emergency_protocols:
st.markdown("""
### 🚨 Emergency Response Protocols
**Immediate Actions During Earthquake:**
- Drop, Cover, and Hold On
- Stay indoors if you're inside
- Move to open area if you're outside
- Stay away from windows, mirrors, and heavy objects
**After Earthquake:**
- Check for injuries and provide first aid
- Check for gas leaks and electrical damage
- Listen to emergency broadcasts
- Be prepared for aftershocks
**Emergency Contacts:**
- Emergency Services: 911 (US) / 112 (EU) / 999 (UK)
- USGS Earthquake Information: https://earthquake.usgs.gov
- Local Emergency Management: Check your local government website
""")
st.markdown("""
### 📊 Current Emergency Status
- **Risk Level**: LOW
- **Recommended Action**: Monitor situation. No immediate action required.
- **Monitoring Required**: No
""")
else:
st.info("Enable Emergency Protocols in Advanced Options to see emergency information.")
with tab6:
st.subheader("🏥 Emergency AI - Standby Mode")
if show_first_aid:
st.markdown("### 🩺 First Aid Training Mode")
injury_type = st.selectbox("Select injury type for training:",
["bleeding", "fracture", "unconscious"])
instructions = emergency_ai.get_first_aid_instructions('injury')
if injury_type in instructions:
st.markdown(f"""
<div class="first-aid-card">
<h4>{injury_type.title()} Management</h4>
</div>
""", unsafe_allow_html=True)
for instruction in instructions[injury_type]:
st.write(instruction)
if show_multilingual:
st.markdown("### 🌐 Emergency Translation Test")
test_message = st.selectbox("Test emergency message:",
["earthquake_alert", "evacuation_order"])
if st.button("🔄 Translate"):
translation = emergency_ai.translate_emergency_message(test_message, emergency_language)
st.success(f"**Translation ({emergency_ai.languages[emergency_language]}):** {translation}")
if show_disaster_learning:
st.markdown("### 🧠 Disaster Learning System")
st.info("Learning system is active and ready to analyze future disasters.")
if emergency_ai.disaster_log:
st.write(f"**Previous disasters analyzed:** {len(emergency_ai.disaster_log)}")
else:
st.write("**Previous disasters analyzed:** 0")
else:
st.success(f"✅ Found {len(df)} earthquakes in the last {hours} hours")
st.write(f"🕐 Last updated: {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')} UTC")
risk_level, risk_score = calculate_overall_risk(df)
# Enhanced risk display with emergency AI features
st.markdown(f"""
<div class="{'emergency-card' if risk_level in ['high', 'severe', 'extreme'] else 'metric-card'}">
<h3>🚨 Current Risk Level: <span class="risk-{risk_level}">{risk_level.upper()}</span></h3>
<p><strong>Risk Score:</strong> {risk_score}</p>
<p><strong>Emergency Protocol:</strong> {EMERGENCY_PROTOCOLS[risk_level]}</p>
</div>
""", unsafe_allow_html=True)
# Emergency AI Alerts
if risk_level in ['high', 'severe', 'extreme']:
if show_first_aid:
first_aid_instructions = emergency_ai.get_first_aid_instructions('earthquake', risk_level)
st.markdown(f"""
<div class="emergency-card">
<h3>🏥 EMERGENCY FIRST AID ACTIVATED</h3>
</div>
""", unsafe_allow_html=True)
for instruction in first_aid_instructions:
st.error(instruction)
if show_rescue_coordination:
coord_plan = emergency_ai.coordinate_rescue_teams(
df.iloc[0] if not df.empty else None, 'earthquake', risk_level
)
st.markdown(f"""
<div class="emergency-card">
<h3>🚁 RESCUE COORDINATION ACTIVATED</h3>
<p><strong>Priority Level:</strong> {coord_plan['priority_level']}</p>
</div>
""", unsafe_allow_html=True)
if show_multilingual:
alert_msg = emergency_ai.translate_emergency_message('earthquake_alert', emergency_language)
st.markdown(f"""
<div class="emergency-card">
<h3>🌐 MULTILINGUAL ALERT</h3>
<p><strong>{emergency_ai.languages[emergency_language]}:</strong> {alert_msg}</p>
</div>
""", unsafe_allow_html=True)
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("Total Earthquakes", len(df))
with col2:
st.metric("Max Magnitude", f"{df['magnitude'].max():.1f}")
with col3:
st.metric("Avg Magnitude", f"{df['magnitude'].mean():.2f}")
with col4:
st.metric("Avg Depth", f"{df['depth'].mean():.1f} km")
tab1, tab2, tab3, tab4, tab5, tab6 = st.tabs(["🗺️ Map", "📊 Analytics", "📋 Data", "🤖 AI Analysis", "🚨 Emergency", "🏥 Emergency AI"])
with tab1:
st.subheader("🌍 Interactive Earthquake Map")
if not df.empty:
try:
map_obj = create_advanced_map(df, region_bbox)
if map_obj:
st_folium(map_obj, width=800, height=500)
else:
st.info("Unable to create map visualization")
except Exception as e:
st.error(f"Error creating map: {str(e)}")
st.info("Try adjusting your search criteria")
else:
st.info("No earthquake data available for map visualization")
with tab2:
st.subheader("📊 Advanced Analytics")
if not df.empty:
try:
analysis = analyze_seismic_patterns(df)
charts = create_comprehensive_charts(df, analysis)
for i, chart in enumerate(charts):
st.plotly_chart(chart, use_container_width=True)
if analysis:
col1, col2 = st.columns(2)
with col1:
st.subheader("📈 Magnitude Statistics")
if 'magnitude_stats' in analysis:
stats_df = pd.DataFrame([analysis['magnitude_stats']]).T
stats_df.columns = ['Value']
st.dataframe(stats_df)
else:
st.info("Insufficient data for magnitude statistics")
with col2:
st.subheader("📊 Risk Distribution")
if 'risk_distribution' in analysis and len(analysis['risk_distribution']) > 0:
risk_df = pd.DataFrame(analysis['risk_distribution'])
risk_df.columns = ['Count']
st.dataframe(risk_df)
else:
st.info("No risk distribution data available")
except Exception as e:
st.error(f"Error in analytics: {str(e)}")
st.info("Try adjusting your search criteria or check your internet connection")
else:
st.info("No earthquake data available for analysis")
with tab3:
st.subheader("📋 Earthquake Data")
if not df.empty:
col1, col2 = st.columns(2)
with col1:
magnitude_filter = st.multiselect(
"Filter by Magnitude Category",
options=df['magnitude_category'].unique(),
default=df['magnitude_category'].unique()
)
with col2:
risk_filter = st.multiselect(
"Filter by Risk Level",
options=df['risk_level'].unique(),
default=df['risk_level'].unique()
)
filtered_df = df[
(df['magnitude_category'].isin(magnitude_filter)) &
(df['risk_level'].isin(risk_filter))
]
st.dataframe(
filtered_df[['time', 'place', 'magnitude', 'depth', 'risk_level', 'time_ago', 'url']],
use_container_width=True
)
csv = filtered_df.to_csv(index=False)
st.download_button(
label="📥 Download CSV",
data=csv,
file_name=f"earthquakes_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
mime="text/csv"
)
with tab4:
st.subheader("🤖 AI-Powered Analysis")
if show_ai_summary and not df.empty:
with st.spinner("🤖 Generating AI analysis..."):
analysis = analyze_seismic_patterns(df)
risk_level, risk_score = calculate_overall_risk(df)
prompt = f"""
As an expert emergency response AI and seismologist, provide a comprehensive analysis of the following earthquake data:
SUMMARY STATISTICS:
- Total earthquakes: {len(df)}
- Time period: {hours} hours
- Magnitude range: {df['magnitude'].min():.1f} - {df['magnitude'].max():.1f}
- Average magnitude: {df['magnitude'].mean():.2f}
- Risk level: {risk_level.upper()}
- Risk score: {risk_score}
RECENT MAJOR EARTHQUAKES:
{df.nlargest(5, 'magnitude')[['time', 'place', 'magnitude', 'depth']].to_string(index=False)}
Please provide:
1. **Emergency Risk Assessment**: Detailed evaluation of immediate dangers
2. **First Aid Priorities**: What medical emergencies to expect and prepare for
3. **Rescue Coordination Needs**: What emergency services and resources are needed
4. **Pattern Analysis**: Identification of concerning seismic patterns
5. **Public Safety Recommendations**: Specific actions for affected populations
6. **Emergency Preparedness**: Immediate and long-term preparedness steps
7. **Monitoring Recommendations**: What to watch for in coming hours/days
8. **Resource Allocation**: Priority areas for emergency resources
Focus on actionable emergency response information and public safety.
"""
summary = get_groq_summary(prompt)
st.markdown(summary)
else:
st.info("Enable AI Summary in Advanced Options to see AI analysis.")
with tab5:
st.subheader("🚨 Emergency Information")
if show_emergency_protocols:
st.markdown("""
### 🚨 Emergency Response Protocols
**Immediate Actions During Earthquake:**
- Drop, Cover, and Hold On
- Stay indoors if you're inside
- Move to open area if you're outside
- Stay away from windows, mirrors, and heavy objects
**After Earthquake:**
- Check for injuries and provide first aid
- Check for gas leaks and electrical damage
- Listen to emergency broadcasts
- Be prepared for aftershocks
**Emergency Contacts:**
- Emergency Services: 911 (US) / 112 (EU) / 999 (UK)
- USGS Earthquake Information: https://earthquake.usgs.gov
- Local Emergency Management: Check your local government website
""")
st.markdown(f"""
### 📊 Current Emergency Status
- **Risk Level**: {risk_level.upper()}
- **Recommended Action**: {EMERGENCY_PROTOCOLS[risk_level]}
- **Monitoring Required**: {'Yes' if risk_level in ['high', 'severe', 'extreme'] else 'No'}
""")
else:
st.info("Enable Emergency Protocols in Advanced Options to see emergency information.")
with tab6:
st.subheader("🏥 Emergency AI Dashboard")
if show_first_aid:
st.markdown("### 🩺 Active First Aid System")
if risk_level in ['high', 'severe', 'extreme']:
first_aid_instructions = emergency_ai.get_first_aid_instructions('earthquake', risk_level)
st.markdown("""
<div class="emergency-card">
<h4>🚨 EARTHQUAKE FIRST AID - ACTIVE EMERGENCY</h4>
</div>
""", unsafe_allow_html=True)
for instruction in first_aid_instructions:
st.error(instruction)
# Post-earthquake care
after_instructions = emergency_ai.get_first_aid_instructions('earthquake')['after']
st.markdown("#### 🏥 After Shaking Stops:")
for instruction in after_instructions:
st.warning(instruction)
else:
st.success("✅ First Aid System Ready - No immediate emergency detected")
st.info("First aid instructions will be automatically activated if seismic risk increases.")
if show_rescue_coordination:
st.markdown("### 🚁 Rescue Coordination System")
if not df.empty:
# Use the first earthquake location as reference
location = df.iloc[0] if not df.empty else {'latitude': 0, 'longitude': 0}
coord_plan = emergency_ai.coordinate_rescue_teams(location, 'earthquake', risk_level)
col1, col2 = st.columns(2)
with col1:
st.markdown(f"""
**Priority Level:** {coord_plan['priority_level']}
**Required Teams:**
""")
for team in coord_plan['required_teams']:
st.write(f"• {team}")
with col2:
st.markdown("**Resource Allocation:**")
for resource in coord_plan['resource_allocation']:
st.write(f"• {resource}")
st.markdown("**Evacuation Zones:**")
for zone, distance in coord_plan['evacuation_zones'].items():
if zone != 'evacuation_routes':
st.write(f"• **{zone.replace('_', ' ').title()}:** {distance}")
else:
st.write(f"• **{zone.replace('_', ' ').title()}:** {distance}")
if show_multilingual:
st.markdown("### 🌐 Multilingual Emergency Alerts")
if risk_level in ['high', 'severe', 'extreme']:
# Show earthquake alert in selected language
alert_translation = emergency_ai.translate_emergency_message('earthquake_alert', emergency_language)
st.markdown(f"""
<div class="emergency-card">
<h4>🚨 ACTIVE ALERT - {emergency_ai.languages[emergency_language].upper()}</h4>
<p style="font-size: 1.2rem; font-weight: bold;">{alert_translation}</p>
</div>
""", unsafe_allow_html=True)
if risk_level == 'extreme':
evacuation_translation = emergency_ai.translate_emergency_message('evacuation_order', emergency_language)
st.markdown(f"""
<div class="emergency-card">
<h4>🚨 EVACUATION ORDER - {emergency_ai.languages[emergency_language].upper()}</h4>
<p style="font-size: 1.2rem; font-weight: bold;">{evacuation_translation}</p>
</div>
""", unsafe_allow_html=True)
# Language support info
st.markdown("**Available Languages:**")
cols = st.columns(3)
for i, (code, name) in enumerate(emergency_ai.languages.items()):
with cols[i % 3]:
if code == emergency_language:
st.success(f"🔹 {name} (Active)")
else:
st.write(f"• {name}")
if show_disaster_learning:
st.markdown("### 🧠 Disaster Learning System")
if risk_level in ['moderate', 'high', 'severe', 'extreme']:
# Simulate learning from current disaster
current_disaster = {
'location': region if region else 'Global',
'magnitude_max': df['magnitude'].max(),
'earthquake_count': len(df),
'risk_level': risk_level,
'response_time': 300, # Simulated 5 minute response time
'effectiveness_rating': 8.5, # Simulated effectiveness
'casualties': 0, # Simulated (would be real data)
'lessons': [
f"High seismic activity detected in {region if region else 'monitored region'}",
f"Maximum magnitude {df['magnitude'].max():.1f} requires {risk_level} response",
"Early warning system functioning correctly",
"Multi-language alerts deployed successfully"
]
}
learning_points = emergency_ai.learn_from_disaster(current_disaster)
st.success("🧠 Learning from current seismic event...")
col1, col2 = st.columns(2)
with col1:
st.markdown("**Current Event Analysis:**")
st.write(f"• Response Time: {learning_points['response_time']} seconds")
st.write(f"• Effectiveness: {learning_points['effectiveness']}/10")
st.write(f"• Casualties: {learning_points['casualties']}")
with col2:
st.markdown("**Lessons Learned:**")
for lesson in learning_points['lessons_learned']:
st.write(f"• {lesson}")
if learning_points['improvements_needed']:
st.markdown("**🔧 Recommended Improvements:**")
for improvement in learning_points['improvements_needed']:
st.warning(f"• {improvement}")
# Historical learning data
if emergency_ai.disaster_log:
st.markdown(f"**📚 Historical Analysis:** {len(emergency_ai.disaster_log)} disasters analyzed")
# Show trend of learning
if len(emergency_ai.disaster_log) >= 2:
recent_effectiveness = [log['learning_points']['effectiveness'] for log in emergency_ai.disaster_log[-5:]]
if recent_effectiveness:
avg_effectiveness = sum(recent_effectiveness) / len(recent_effectiveness)
st.metric("Average Response Effectiveness", f"{avg_effectiveness:.1f}/10")
else:
st.info("No historical disaster data available yet.")