#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Oklahoma Damage Assessment System with Comprehensive Sentiment Analysis Optimized for Hugging Face Spaces deployment """ import streamlit as st import pandas as pd import numpy as np import plotly.express as px import plotly.graph_objects as go from datetime import datetime, timedelta import random import json from typing import Dict, List, Tuple, Optional import time import os # Hugging Face optimization os.environ['STREAMLIT_BROWSER_GATHER_USAGE_STATS'] = 'false' # Page configuration - MUST be first Streamlit command st.set_page_config( page_title="🌪️ Oklahoma Damage Assessment", page_icon="⚠️", layout="wide", initial_sidebar_state="expanded", menu_items={ 'Get Help': 'https://github.com/your-repo/oklahoma-damage-assessment', 'Report a bug': 'https://github.com/your-repo/oklahoma-damage-assessment/issues', 'About': "# Oklahoma Damage Assessment System\nComprehensive disaster impact analysis with sentiment analysis!" } ) # Enhanced CSS for better Hugging Face compatibility def load_css(): st.markdown(""" """, unsafe_allow_html=True) # Data Management with Closures (Simplified for HF) @st.cache_data def get_location_data(): """Get Oklahoma location data with closure pattern""" counties = [ 'Oklahoma', 'Tulsa', 'Cleveland', 'Canadian', 'Comanche', 'Garfield', 'Rogers', 'Washington', 'Pottawatomie', 'Creek', 'Kay', 'Carter', 'Payne', 'McClain', 'Grady', 'Stephens', 'Pontotoc', 'Lincoln' ] cities = [ 'Oklahoma City', 'Tulsa', 'Norman', 'Lawton', 'Edmond', 'Moore', 'Midwest City', 'Enid', 'Stillwater', 'Muskogee', 'Bartlesville', 'Owasso', 'Shawnee', 'Yukon', 'Ardmore', 'Ponca City' ] return { 'counties': counties, 'cities': cities } @st.cache_data def get_sentiment_lexicon(): """Get emotional lexicon for sentiment analysis""" return { 'devastating': {'sentiment': -0.95, 'emotion': 'despair', 'intensity': 'extreme'}, 'catastrophic': {'sentiment': -0.90, 'emotion': 'terror', 'intensity': 'extreme'}, 'destroyed': {'sentiment': -0.85, 'emotion': 'grief', 'intensity': 'high'}, 'damaged': {'sentiment': -0.65, 'emotion': 'distress', 'intensity': 'moderate'}, 'threatened': {'sentiment': -0.60, 'emotion': 'anxiety', 'intensity': 'moderate'}, 'displaced': {'sentiment': -0.75, 'emotion': 'fear', 'intensity': 'high'}, 'injured': {'sentiment': -0.80, 'emotion': 'pain', 'intensity': 'high'}, 'affected': {'sentiment': -0.45, 'emotion': 'concern', 'intensity': 'moderate'}, 'recovering': {'sentiment': 0.50, 'emotion': 'hope', 'intensity': 'moderate'}, 'resilient': {'sentiment': 0.70, 'emotion': 'strength', 'intensity': 'high'}, 'helping': {'sentiment': 0.60, 'emotion': 'compassion', 'intensity': 'moderate'}, 'support': {'sentiment': 0.55, 'emotion': 'comfort', 'intensity': 'moderate'} } def analyze_sentiment(text): """Simplified sentiment analysis""" lexicon = get_sentiment_lexicon() words = text.lower().split() sentiments = [] emotions = {} for word in words: clean_word = ''.join(c for c in word if c.isalnum()) if clean_word in lexicon: data = lexicon[clean_word] sentiments.append(data['sentiment']) emotions[data['emotion']] = emotions.get(data['emotion'], 0) + 1 avg_sentiment = np.mean(sentiments) if sentiments else 0.0 dominant_emotion = max(emotions.items(), key=lambda x: x[1])[0] if emotions else 'neutral' # Classification if avg_sentiment <= -0.6: classification = 'highly_negative' elif avg_sentiment <= -0.3: classification = 'negative' elif avg_sentiment <= 0.3: classification = 'neutral' else: classification = 'positive' return { 'sentiment_score': avg_sentiment, 'classification': classification, 'dominant_emotion': dominant_emotion, 'emotion_distribution': emotions } def generate_damage_data(location): """Generate comprehensive damage data""" damage_types = [ {'id': 'drought', 'name': 'Drought', 'color': '#ff8c00', 'icon': '🌵'}, {'id': 'flood', 'name': 'Flood', 'color': '#1e90ff', 'icon': '🌊'}, {'id': 'tornado', 'name': 'Tornado', 'color': '#dc143c', 'icon': '🌪️'}, {'id': 'wildfire', 'name': 'Wildfire', 'color': '#ff4500', 'icon': '🔥'}, {'id': 'hail', 'name': 'Hail Storm', 'color': '#87ceeb', 'icon': '🌧️'}, {'id': 'wind', 'name': 'High Winds', 'color': '#a9a9a9', 'icon': '💨'} ] severity_levels = [ {'id': 1, 'name': 'Minimal', 'color': '#fff3cd'}, {'id': 2, 'name': 'Minor', 'color': '#ffeeba'}, {'id': 3, 'name': 'Moderate', 'color': '#ffdf7e'}, {'id': 4, 'name': 'Severe', 'color': '#ffcc00'}, {'id': 5, 'name': 'Extreme', 'color': '#ff8c00'} ] damage_type = random.choice(damage_types) severity = random.choice(severity_levels) impact_templates = { 'drought': "Agricultural operations in {location} are experiencing {severity_adj} stress, causing {emotion} in farming communities", 'flood': "Flash flooding in {location} has {severity_adj} damaged infrastructure, creating {emotion} among residents", 'tornado': "Tornado touchdown in {location} has {severity_adj} damaged structures, leaving survivors with {emotion}", 'wildfire': "Wildfire near {location} has {severity_adj} threatened areas, forcing evacuations and causing {emotion}", 'hail': "Severe hail storm in {location} has {severity_adj} damaged property, creating {emotion} among homeowners", 'wind': "High winds in {location} have {severity_adj} damaged infrastructure, causing {emotion} in the community" } severity_adjectives = { 1: 'slightly', 2: 'moderately', 3: 'significantly', 4: 'severely', 5: 'catastrophically' } emotions = { 1: 'mild concern', 2: 'growing anxiety', 3: 'widespread distress', 4: 'severe trauma', 5: 'overwhelming devastation' } impact_text = impact_templates[damage_type['id']].format( location=location, severity_adj=severity_adjectives[severity['id']], emotion=emotions[severity['id']] ) base_multiplier = severity['id'] population_factor = 1.5 if 'City' in location else 1.0 assessments = { 'people': { 'injured': int(random.randint(0, 20) * base_multiplier), 'displaced': int(random.randint(0, 100) * base_multiplier), 'affected': int(random.randint(100, 1000) * base_multiplier * population_factor), 'psychologicalCasualties': int(random.randint(50, 300) * base_multiplier), 'communityMorale': max(20, 100 - (base_multiplier * random.randint(15, 25))) }, 'property': { 'homes_damaged': int(random.randint(0, 100) * base_multiplier), 'businesses_affected': int(random.randint(0, 25) * base_multiplier), 'estimated_cost': int(random.randint(100000, 5000000) * base_multiplier) }, 'infrastructure': { 'roads_damaged_miles': round(random.uniform(1, 30) * base_multiplier, 1), 'power_outages': int(random.randint(500, 10000) * base_multiplier), 'water_systems_affected': int(random.randint(0, 10) * base_multiplier) }, 'agriculture': { 'crop_loss_acres': int(random.randint(500, 10000) * base_multiplier), 'livestock_loss': int(random.randint(0, 200) * base_multiplier), 'estimated_cost': int(random.randint(100000, 2000000) * base_multiplier) } } return { 'location': location, 'damageType': damage_type, 'severity': severity, 'impact': impact_text, 'assessments': assessments, 'timestamp': datetime.now().isoformat() } def calculate_psychological_impact(assessments): """Calculate psychological impact score""" people_impact = min(1.0, ( assessments['people']['injured'] * 0.1 + assessments['people']['displaced'] * 0.05 + assessments['people']['affected'] * 0.0005 )) property_impact = min(1.0, assessments['property']['homes_damaged'] * 0.01) economic_impact = min(1.0, assessments['property']['estimated_cost'] / 10000000) total_impact = (people_impact * 0.5 + property_impact * 0.3 + economic_impact * 0.2) if total_impact < 0.25: level = 'minimal' elif total_impact < 0.5: level = 'moderate' elif total_impact < 0.75: level = 'severe' else: level = 'critical' return { 'total_score': total_impact, 'level': level, 'components': { 'people_impact': people_impact, 'property_impact': property_impact, 'economic_impact': economic_impact } } def assess_trauma_risk(assessments): """Assess trauma risk indicators""" indicators = { 'direct_victimization': assessments['people']['injured'] > 0, 'home_destruction': assessments['property']['homes_damaged'] > 0, 'economic_devastation': assessments['property']['estimated_cost'] > 1000000, 'social_disruption': assessments['people']['displaced'] > 50, 'infrastructure_collapse': assessments['infrastructure']['power_outages'] > 5000, 'community_breakdown': assessments['people']['communityMorale'] < 50 } active_indicators = sum(indicators.values()) risk_score = active_indicators / len(indicators) if risk_score < 0.3: risk_level = 'low' elif risk_score < 0.6: risk_level = 'moderate' else: risk_level = 'high' return { 'indicators': indicators, 'active_count': active_indicators, 'risk_score': risk_score, 'risk_level': risk_level } def calculate_overall_mental_health(sentiment_data, psych_impact, trauma_risk, community_morale): """Calculate overall mental health score""" sentiment_score = (sentiment_data['sentiment_score'] + 1) / 2 # Normalize to 0-1 psychological_score = 1 - psych_impact['total_score'] trauma_score = 1 - trauma_risk['risk_score'] morale_score = community_morale / 100 overall_score = ( sentiment_score * 0.25 + psychological_score * 0.35 + trauma_score * 0.25 + morale_score * 0.15 ) if overall_score > 0.75: level = 'excellent' elif overall_score > 0.6: level = 'good' elif overall_score > 0.4: level = 'concerning' else: level = 'critical' return { 'overall_score': overall_score, 'level': level, 'components': { 'sentiment': sentiment_score, 'psychological': psychological_score, 'trauma': trauma_score, 'morale': morale_score } } def main(): """Main application function""" # Load CSS load_css() # Header st.markdown("""

⚠️ Oklahoma Damage Assessment System

🧠 Comprehensive Sentiment & Psychological Analysis

Advanced disaster impact analysis with emotional and mental health assessment

""", unsafe_allow_html=True) # Sidebar controls st.sidebar.title("🎛️ Assessment Controls") st.sidebar.markdown("---") location_data = get_location_data() # Location selection location_type = st.sidebar.radio("📍 Location Type", ["County", "City"]) if location_type == "County": selected_location = st.sidebar.selectbox("🏛️ Select County", location_data['counties']) else: selected_location = st.sidebar.selectbox("🏙️ Select City", location_data['cities']) # Analysis options st.sidebar.markdown("---") st.sidebar.subheader("🔧 Analysis Options") show_detailed = st.sidebar.checkbox("Show Detailed Analysis", value=True) show_trauma = st.sidebar.checkbox("Show Trauma Assessment", value=True) show_timeline = st.sidebar.checkbox("Show Recovery Timeline", value=True) # Generate new assessment button if st.sidebar.button("🔄 Generate New Assessment", type="primary"): st.rerun() # Generate data if 'damage_data' not in st.session_state or st.sidebar.button("🔄 Refresh Data"): st.session_state.damage_data = generate_damage_data(selected_location) damage_data = st.session_state.damage_data # Update location if changed if damage_data['location'] != selected_location: damage_data = generate_damage_data(selected_location) st.session_state.damage_data = damage_data # Perform analysis sentiment_data = analyze_sentiment(damage_data['impact']) psych_impact = calculate_psychological_impact(damage_data['assessments']) trauma_risk = assess_trauma_risk(damage_data['assessments']) overall_mental_health = calculate_overall_mental_health( sentiment_data, psych_impact, trauma_risk, damage_data['assessments']['people']['communityMorale'] ) # Main damage alert damage_type = damage_data['damageType'] severity = damage_data['severity'] st.markdown(f"""

{damage_type['icon']} {damage_data['location']} Impact Assessment

{damage_type['name']} - {severity['name']} Severity

Impact: {damage_data['impact']}

""", unsafe_allow_html=True) # Mental health overview overall_score = overall_mental_health['overall_score'] level = overall_mental_health['level'] color_map = { 'excellent': '#28a745', 'good': '#17a2b8', 'concerning': '#ffc107', 'critical': '#dc3545' } color = color_map.get(level, '#6c757d') st.markdown(f"""

🎯 Overall Community Mental Health Assessment

{overall_score:.1%}

Mental Health Score

{level.upper()}

Status Level

""", unsafe_allow_html=True) # Key metrics st.subheader("📊 Key Impact Metrics") col1, col2, col3, col4 = st.columns(4) assessments = damage_data['assessments'] with col1: st.metric("🚑 Injured", assessments['people']['injured']) st.metric("🧠 Psychological", assessments['people']['psychologicalCasualties']) with col2: st.metric("🏠 Homes Damaged", assessments['property']['homes_damaged']) st.metric("🚗 Property Cost", f"${assessments['property']['estimated_cost']:,}") with col3: st.metric("👥 Affected", assessments['people']['affected']) st.metric("🏠 Displaced", assessments['people']['displaced']) with col4: st.metric("💪 Community Morale", f"{assessments['people']['communityMorale']}%") st.metric("⚡ Power Outages", f"{assessments['infrastructure']['power_outages']:,}") # Detailed analysis sections if show_detailed: st.subheader("📈 Detailed Sentiment Analysis") col1, col2 = st.columns(2) with col1: st.markdown("**Text Sentiment Analysis:**") classification = sentiment_data['classification'] class_colors = { 'highly_negative': '#dc3545', 'negative': '#fd7e14', 'neutral': '#6c757d', 'positive': '#28a745' } st.markdown(f"""
Classification: {classification.replace('_', ' ').title()}
Sentiment Score: {sentiment_data['sentiment_score']:.3f}
Dominant Emotion: {sentiment_data['dominant_emotion'].title()}
""", unsafe_allow_html=True) with col2: st.markdown("**Psychological Impact Analysis:**") level_colors = { 'minimal': '#28a745', 'moderate': '#ffc107', 'severe': '#fd7e14', 'critical': '#dc3545' } level_color = level_colors.get(psych_impact['level'], '#6c757d') st.markdown(f"""
Impact Level: {psych_impact['level'].title()}
Total Score: {psych_impact['total_score']:.3f}
Primary Factors: People Impact, Property Loss, Economic Stress
""", unsafe_allow_html=True) # Trauma assessment if show_trauma: st.subheader("⚠️ Trauma Risk Assessment") col1, col2, col3 = st.columns(3) with col1: st.metric("⚠️ Risk Level", trauma_risk['risk_level'].upper()) with col2: st.metric("🚨 Active Indicators", f"{trauma_risk['active_count']}/6") with col3: st.metric("📊 Risk Score", f"{trauma_risk['risk_score']:.1%}") # Trauma indicators st.markdown("**Trauma Risk Indicators:**") indicators_data = [] for indicator, active in trauma_risk['indicators'].items(): indicators_data.append({ 'Indicator': indicator.replace('_', ' ').title(), 'Status': 'Active' if active else 'Inactive', 'Risk_Level': 1 if active else 0 }) indicators_df = pd.DataFrame(indicators_data) if not indicators_df.empty: fig = px.bar( indicators_df, x='Indicator', y='Risk_Level', color='Status', title="Trauma Risk Indicators", color_discrete_map={'Active': '#dc3545', 'Inactive': '#28a745'} ) fig.update_layout(height=400, xaxis_tickangle=-45) st.plotly_chart(fig, use_container_width=True) # Recovery timeline if show_timeline: st.subheader("📅 Recovery Timeline") timeline_phases = [ ("Immediate Response", "0-72 hours", "Acute stress management"), ("Short-term Recovery", "3 days - 4 weeks", "PTSD prevention"), ("Medium-term Adjustment", "1-6 months", "Adaptation support"), ("Long-term Recovery", "6+ months", "Post-traumatic growth") ] for i, (phase, duration, description) in enumerate(timeline_phases, 1): with st.expander(f"Phase {i}: {phase} ({duration})"): st.write(f"**Focus:** {description}") if i == 1: st.write(f"• Expected acute stress in {trauma_risk['risk_score']:.1%} of population") st.write("• Deploy crisis counselors immediately") elif i == 2: st.write(f"• PTSD screening for {trauma_risk['active_count'] * 100} individuals") st.write("• Establish support groups") elif i == 3: st.write("• Economic counseling for affected households") st.write("• Long-term housing solutions") else: st.write(f"• Post-traumatic growth potential: {overall_score:.1%}") st.write("• Community resilience building") # Mental health resources st.subheader("🏥 Mental Health Resource Recommendations") total_affected = assessments['people']['affected'] psychological_casualties = assessments['people']['psychologicalCasualties'] col1, col2, col3 = st.columns(3) with col1: st.markdown("**🚨 Immediate Response**") counselors_needed = max(5, psychological_casualties // 50) st.write(f"• Deploy {counselors_needed} crisis counselors") st.write("• Activate 24/7 mental health hotline") st.write("• Set up mobile crisis units") with col2: st.markdown("**⏰ Short-term Support**") support_groups = max(3, total_affected // 200) st.write(f"• Establish {support_groups} support groups") st.write("• Trauma screening programs") st.write("• Children's mental health services") with col3: st.markdown("**🌱 Long-term Recovery**") st.write("• Community resilience workshops") st.write("• PTSD treatment programs") st.write("• Economic counseling services") # Data export st.sidebar.markdown("---") st.sidebar.subheader("📊 Export Data") if st.sidebar.button("📥 Export Assessment"): export_data = { 'damage_assessment': damage_data, 'sentiment_analysis': sentiment_data, 'psychological_impact': psych_impact, 'trauma_assessment': trauma_risk, 'mental_health_score': overall_mental_health, 'generated_at': datetime.now().isoformat() } st.sidebar.download_button( label="Download JSON Report", data=json.dumps(export_data, indent=2, default=str), file_name=f"oklahoma_assessment_{selected_location.replace(' ', '_')}.json", mime="application/json" ) # Footer st.markdown("---") st.markdown("""

⚠️ Oklahoma Damage Assessment System

🧠 Comprehensive Sentiment & Psychological Analysis Platform

Last Updated: {}

""".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S')), unsafe_allow_html=True) if __name__ == "__main__": main()