Navya-Sree commited on
Commit
4e33c9f
Β·
verified Β·
1 Parent(s): efad454

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +1703 -0
app.py ADDED
@@ -0,0 +1,1703 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import numpy as np
3
+ import plotly.express as px
4
+ import plotly.graph_objects as go
5
+ from plotly.subplots import make_subplots
6
+ import streamlit as st
7
+ from datetime import datetime
8
+ import folium
9
+ from streamlit_folium import st_folium
10
+ from scipy import stats
11
+ import warnings
12
+ warnings.filterwarnings('ignore')
13
+
14
+ # ===================================
15
+ # PAGE SETUP
16
+ # ===================================
17
+ st.set_page_config(
18
+ page_title="Oklahoma Flood Research Dashboard",
19
+ page_icon="🌊",
20
+ layout="wide",
21
+ initial_sidebar_state="expanded"
22
+ )
23
+
24
+ # ===================================
25
+ # STYLING
26
+ # ===================================
27
+ st.markdown("""
28
+ <style>
29
+ .main-header {
30
+ font-size: 2.8rem;
31
+ color: #1a365d;
32
+ text-align: center;
33
+ margin-bottom: 1rem;
34
+ font-weight: bold;
35
+ }
36
+ .sub-header {
37
+ font-size: 1.8rem;
38
+ color: #2d3748;
39
+ margin: 1.5rem 0 1rem 0;
40
+ border-bottom: 2px solid #4299e1;
41
+ padding-bottom: 0.5rem;
42
+ }
43
+ .insight-box {
44
+ background: linear-gradient(135deg, #e6f3ff 0%, #f0f8ff 100%);
45
+ padding: 1.5rem;
46
+ border-radius: 12px;
47
+ margin: 1rem 0;
48
+ border-left: 5px solid #4299e1;
49
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
50
+ }
51
+ .metric-card {
52
+ background: white;
53
+ padding: 1rem;
54
+ border-radius: 8px;
55
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
56
+ border-top: 3px solid #4299e1;
57
+ }
58
+ .statistical-box {
59
+ background: linear-gradient(135deg, #fff5f5 0%, #fed7d7 100%);
60
+ padding: 1rem;
61
+ border-radius: 8px;
62
+ border-left: 4px solid #e53e3e;
63
+ margin: 1rem 0;
64
+ }
65
+ </style>
66
+ """, unsafe_allow_html=True)
67
+
68
+ # ===================================
69
+ # DATA FUNCTIONS
70
+ # ===================================
71
+ @st.cache_data
72
+ def load_county_data():
73
+ """Load Oklahoma county information"""
74
+ return {
75
+ 'Oklahoma': {
76
+ 'full_name': 'Oklahoma County',
77
+ 'seat': 'Oklahoma City',
78
+ 'population': 796292,
79
+ 'latitude': 35.4676,
80
+ 'longitude': -97.5164,
81
+ 'elevation_ft': 1200,
82
+ 'major_rivers': ['North Canadian River', 'Canadian River'],
83
+ 'tribal_nations': ['Citizen Potawatomi Nation'],
84
+ 'severity_level': 'High',
85
+ 'research_notes': 'Most flood-prone county in Oklahoma. Urban development increases flash flood risk.',
86
+ 'climate_projection': '68% higher heavy rainfall risks by 2090',
87
+ 'vulnerability_factors': ['Urban heat island', 'Impermeable surfaces', 'Dense population']
88
+ },
89
+ 'Tulsa': {
90
+ 'full_name': 'Tulsa County',
91
+ 'seat': 'Tulsa',
92
+ 'population': 669279,
93
+ 'latitude': 36.1540,
94
+ 'longitude': -95.9928,
95
+ 'elevation_ft': 700,
96
+ 'major_rivers': ['Arkansas River', 'Verdigris River'],
97
+ 'tribal_nations': ['Muscogee Creek Nation', 'Cherokee Nation'],
98
+ 'severity_level': 'High',
99
+ 'research_notes': 'Arkansas River flooding history. 2019 flooding caused $3.4B+ damage.',
100
+ 'climate_projection': '64% higher 2-year flooding risks',
101
+ 'vulnerability_factors': ['River proximity', 'Aging infrastructure', 'Climate change']
102
+ },
103
+ 'Cleveland': {
104
+ 'full_name': 'Cleveland County',
105
+ 'seat': 'Norman',
106
+ 'population': 295528,
107
+ 'latitude': 35.2226,
108
+ 'longitude': -97.4395,
109
+ 'elevation_ft': 1100,
110
+ 'major_rivers': ['Canadian River', 'Little River'],
111
+ 'tribal_nations': ['Absentee Shawnee Tribe'],
112
+ 'severity_level': 'Medium',
113
+ 'research_notes': 'Canadian River corridor flooding. University area vulnerable.',
114
+ 'climate_projection': 'Moderate increase in extreme precipitation',
115
+ 'vulnerability_factors': ['Student population', 'River proximity']
116
+ },
117
+ 'Canadian': {
118
+ 'full_name': 'Canadian County',
119
+ 'seat': 'El Reno',
120
+ 'population': 154405,
121
+ 'latitude': 35.5317,
122
+ 'longitude': -98.1020,
123
+ 'elevation_ft': 1300,
124
+ 'major_rivers': ['Canadian River', 'North Canadian River'],
125
+ 'tribal_nations': ['Cheyenne and Arapaho Tribes'],
126
+ 'severity_level': 'Medium',
127
+ 'research_notes': 'Rural flooding patterns. Agricultural impact significant.',
128
+ 'climate_projection': 'Agricultural flood losses projected to increase 20%',
129
+ 'vulnerability_factors': ['Agricultural exposure', 'Rural emergency response']
130
+ },
131
+ 'Creek': {
132
+ 'full_name': 'Creek County',
133
+ 'seat': 'Sapulpa',
134
+ 'population': 71754,
135
+ 'latitude': 35.9951,
136
+ 'longitude': -96.1142,
137
+ 'elevation_ft': 800,
138
+ 'major_rivers': ['Arkansas River', 'Deep Fork River'],
139
+ 'tribal_nations': ['Muscogee Creek Nation'],
140
+ 'severity_level': 'High',
141
+ 'research_notes': 'Adjacent to Tulsa County. Tribal lands vulnerable.',
142
+ 'climate_projection': '64% higher flash flooding risks for tribal communities',
143
+ 'vulnerability_factors': ['Tribal community exposure', 'River connectivity']
144
+ },
145
+ 'Muskogee': {
146
+ 'full_name': 'Muskogee County',
147
+ 'seat': 'Muskogee',
148
+ 'population': 66339,
149
+ 'latitude': 35.7478,
150
+ 'longitude': -95.3697,
151
+ 'elevation_ft': 600,
152
+ 'major_rivers': ['Arkansas River', 'Verdigris River'],
153
+ 'tribal_nations': ['Muscogee Creek Nation', 'Cherokee Nation'],
154
+ 'severity_level': 'High',
155
+ 'research_notes': '2019 Arkansas River flooding severely impacted.',
156
+ 'climate_projection': 'Highest vulnerability among tribal nations',
157
+ 'vulnerability_factors': ['Multiple river convergence', 'Tribal infrastructure']
158
+ },
159
+ 'Grady': {
160
+ 'full_name': 'Grady County',
161
+ 'seat': 'Chickasha',
162
+ 'population': 54795,
163
+ 'latitude': 35.0526,
164
+ 'longitude': -97.9364,
165
+ 'elevation_ft': 1150,
166
+ 'major_rivers': ['Washita River', 'Canadian River'],
167
+ 'tribal_nations': ['Anadarko Caddo Nation'],
168
+ 'severity_level': 'Medium',
169
+ 'research_notes': 'Recent dam breaches (2025). Small watershed dams critical.',
170
+ 'climate_projection': 'Dam effectiveness declining with increased precipitation',
171
+ 'vulnerability_factors': ['Dam infrastructure aging', 'Rural isolation']
172
+ },
173
+ 'Payne': {
174
+ 'full_name': 'Payne County',
175
+ 'seat': 'Stillwater',
176
+ 'population': 81912,
177
+ 'latitude': 36.1156,
178
+ 'longitude': -97.0589,
179
+ 'elevation_ft': 900,
180
+ 'major_rivers': ['Stillwater Creek', 'Cimarron River'],
181
+ 'tribal_nations': ['Osage Nation'],
182
+ 'severity_level': 'Low',
183
+ 'research_notes': 'University town with good drainage.',
184
+ 'climate_projection': 'Stable flood risk with adequate infrastructure',
185
+ 'vulnerability_factors': ['Student population during events']
186
+ }
187
+ }
188
+
189
+ def calculate_severity(damage, fatalities, injuries):
190
+ """Calculate flood severity level"""
191
+ damage_score = 3 if damage >= 50_000_000 else 2 if damage >= 10_000_000 else 1 if damage >= 1_000_000 else 0
192
+ casualty_score = 3 if (fatalities + injuries) >= 10 else 2 if (fatalities + injuries) >= 3 else 1 if (fatalities + injuries) >= 1 else 0
193
+
194
+ if fatalities > 0:
195
+ casualty_score = max(casualty_score, 2)
196
+
197
+ max_score = max(damage_score, casualty_score)
198
+ return 'High' if max_score >= 3 else 'Medium' if max_score >= 2 else 'Low'
199
+
200
+ def classify_damage(damage):
201
+ """Classify damage level"""
202
+ if damage >= 50_000_000:
203
+ return 'Catastrophic'
204
+ elif damage >= 10_000_000:
205
+ return 'Major'
206
+ elif damage >= 1_000_000:
207
+ return 'Moderate'
208
+ else:
209
+ return 'Minor'
210
+
211
+ @st.cache_data
212
+ def load_flood_data():
213
+ """Load flood event data"""
214
+ events = [
215
+ # 2025 Events
216
+ {
217
+ 'date': '2025-04-30',
218
+ 'county': 'Oklahoma',
219
+ 'location': 'Oklahoma City Metro',
220
+ 'type': 'Flash Flood',
221
+ 'source': 'Heavy Rainfall - Record Breaking',
222
+ 'fatalities': 2,
223
+ 'injuries': 5,
224
+ 'damage_usd': 15_000_000,
225
+ 'rain_inches': 12.5,
226
+ 'description': 'Historic April flooding broke 77-year rainfall record.',
227
+ 'impact_details': 'Record rainfall, 47 road closures, 156 water rescues',
228
+ 'research_significance': 'Validates climate projections for increased extreme precipitation',
229
+ 'tribal_impact': 'Citizen Potawatomi Nation facilities flooded',
230
+ 'data_source': 'Oklahoma Emergency Management'
231
+ },
232
+ {
233
+ 'date': '2025-05-02',
234
+ 'county': 'Grady',
235
+ 'location': 'County Line and County Road 1322',
236
+ 'type': 'Dam Break',
237
+ 'source': 'Infrastructure Failure',
238
+ 'fatalities': 0,
239
+ 'injuries': 0,
240
+ 'damage_usd': 2_000_000,
241
+ 'rain_inches': 8.0,
242
+ 'description': 'Small watershed dam breach isolated 8-10 homes.',
243
+ 'impact_details': 'Dam failure, home isolation, emergency road construction',
244
+ 'research_significance': 'Highlights need for dam maintenance',
245
+ 'tribal_impact': 'No direct tribal impact',
246
+ 'data_source': 'Oklahoma Water Resources Board'
247
+ },
248
+ # 2024 Events
249
+ {
250
+ 'date': '2024-04-27',
251
+ 'county': 'Oklahoma',
252
+ 'location': 'Multiple OKC Metro locations',
253
+ 'type': 'Flash Flood',
254
+ 'source': 'Severe Storms and Tornadoes',
255
+ 'fatalities': 1,
256
+ 'injuries': 15,
257
+ 'damage_usd': 25_000_000,
258
+ 'rain_inches': 6.8,
259
+ 'description': 'Part of major tornado outbreak with significant flooding.',
260
+ 'impact_details': 'Combined tornado-flood event, 85,000 power outages',
261
+ 'research_significance': 'Demonstrates multi-hazard vulnerability',
262
+ 'tribal_impact': 'Absentee Shawnee tribal facilities damaged',
263
+ 'data_source': 'National Weather Service'
264
+ },
265
+ {
266
+ 'date': '2024-06-15',
267
+ 'county': 'Tulsa',
268
+ 'location': 'Tulsa Metro',
269
+ 'type': 'Flash Flood',
270
+ 'source': 'Severe Thunderstorms',
271
+ 'fatalities': 0,
272
+ 'injuries': 3,
273
+ 'damage_usd': 8_500_000,
274
+ 'rain_inches': 5.2,
275
+ 'description': 'Urban flash flooding from intense thunderstorms.',
276
+ 'impact_details': 'Downtown flooding, vehicle rescues',
277
+ 'research_significance': 'Urban drainage system capacity exceeded',
278
+ 'tribal_impact': 'Limited impact on Creek Nation facilities',
279
+ 'data_source': 'Tulsa Emergency Management'
280
+ },
281
+ # 2023 Events
282
+ {
283
+ 'date': '2023-05-20',
284
+ 'county': 'Creek',
285
+ 'location': 'Sapulpa area',
286
+ 'type': 'Flash Flood',
287
+ 'source': 'Heavy Rainfall',
288
+ 'fatalities': 0,
289
+ 'injuries': 2,
290
+ 'damage_usd': 6_200_000,
291
+ 'rain_inches': 4.8,
292
+ 'description': 'Flash flooding affected tribal communities.',
293
+ 'impact_details': 'Tribal community center flooded, road closures',
294
+ 'research_significance': 'Tribal infrastructure vulnerability demonstrated',
295
+ 'tribal_impact': 'Muscogee Creek Nation community facilities damaged',
296
+ 'data_source': 'Creek County Emergency Management'
297
+ },
298
+ {
299
+ 'date': '2023-07-12',
300
+ 'county': 'Canadian',
301
+ 'location': 'El Reno area',
302
+ 'type': 'Flash Flood',
303
+ 'source': 'Severe Storms',
304
+ 'fatalities': 0,
305
+ 'injuries': 1,
306
+ 'damage_usd': 4_100_000,
307
+ 'rain_inches': 3.9,
308
+ 'description': 'Rural flooding with agricultural impacts.',
309
+ 'impact_details': 'Crop damage, livestock evacuation',
310
+ 'research_significance': 'Rural agricultural vulnerability patterns',
311
+ 'tribal_impact': 'Cheyenne-Arapaho agricultural lands affected',
312
+ 'data_source': 'Canadian County Emergency Management'
313
+ },
314
+ # 2022 Events
315
+ {
316
+ 'date': '2022-05-15',
317
+ 'county': 'Cleveland',
318
+ 'location': 'Norman',
319
+ 'type': 'Flash Flood',
320
+ 'source': 'Thunderstorms',
321
+ 'fatalities': 0,
322
+ 'injuries': 4,
323
+ 'damage_usd': 7_800_000,
324
+ 'rain_inches': 4.5,
325
+ 'description': 'Norman flooding affected university area.',
326
+ 'impact_details': 'OU campus flooding, residential damage',
327
+ 'research_significance': 'University town vulnerability assessment',
328
+ 'tribal_impact': 'No significant tribal impact',
329
+ 'data_source': 'Cleveland County Emergency Management'
330
+ },
331
+ {
332
+ 'date': '2022-08-22',
333
+ 'county': 'Muskogee',
334
+ 'location': 'Muskogee',
335
+ 'type': 'Flash Flood',
336
+ 'source': 'Heavy Rainfall',
337
+ 'fatalities': 1,
338
+ 'injuries': 3,
339
+ 'damage_usd': 9_300_000,
340
+ 'rain_inches': 5.8,
341
+ 'description': 'Urban flooding with tribal headquarters impact.',
342
+ 'impact_details': 'Downtown flooding, tribal building damage',
343
+ 'research_significance': 'Tribal government infrastructure vulnerability',
344
+ 'tribal_impact': 'Muscogee Creek Nation headquarters affected',
345
+ 'data_source': 'Muskogee County Emergency Management'
346
+ },
347
+ # 2021 Events
348
+ {
349
+ 'date': '2021-04-28',
350
+ 'county': 'Oklahoma',
351
+ 'location': 'Oklahoma City',
352
+ 'type': 'Flash Flood',
353
+ 'source': 'Severe Weather Complex',
354
+ 'fatalities': 1,
355
+ 'injuries': 8,
356
+ 'damage_usd': 12_400_000,
357
+ 'rain_inches': 6.2,
358
+ 'description': 'Spring flooding event with tornado warnings.',
359
+ 'impact_details': 'Multi-hazard event, emergency shelter activation',
360
+ 'research_significance': 'Multi-hazard interaction patterns',
361
+ 'tribal_impact': 'Limited tribal impact',
362
+ 'data_source': 'Oklahoma Emergency Management'
363
+ },
364
+ {
365
+ 'date': '2021-06-10',
366
+ 'county': 'Payne',
367
+ 'location': 'Stillwater',
368
+ 'type': 'Flash Flood',
369
+ 'source': 'Stillwater Creek Overflow',
370
+ 'fatalities': 0,
371
+ 'injuries': 2,
372
+ 'damage_usd': 3_800_000,
373
+ 'rain_inches': 4.1,
374
+ 'description': 'Stillwater Creek flooding affected OSU campus.',
375
+ 'impact_details': 'OSU campus impacts, downtown business flooding',
376
+ 'research_significance': 'Effective flood management demonstration',
377
+ 'tribal_impact': 'No significant tribal impact',
378
+ 'data_source': 'Payne County Emergency Management'
379
+ },
380
+ # 2020 Events
381
+ {
382
+ 'date': '2020-05-25',
383
+ 'county': 'Tulsa',
384
+ 'location': 'Arkansas River corridor',
385
+ 'type': 'River Flood',
386
+ 'source': 'Heavy Regional Rainfall',
387
+ 'fatalities': 0,
388
+ 'injuries': 2,
389
+ 'damage_usd': 18_600_000,
390
+ 'rain_inches': 8.4,
391
+ 'description': 'Arkansas River flooding with levee stress.',
392
+ 'impact_details': 'Levee monitoring, evacuations considered',
393
+ 'research_significance': 'River system stress testing',
394
+ 'tribal_impact': 'Creek Nation riverside properties affected',
395
+ 'data_source': 'US Army Corps of Engineers'
396
+ },
397
+ {
398
+ 'date': '2020-07-18',
399
+ 'county': 'Canadian',
400
+ 'location': 'Rural Canadian County',
401
+ 'type': 'Flash Flood',
402
+ 'source': 'Isolated Severe Storms',
403
+ 'fatalities': 0,
404
+ 'injuries': 0,
405
+ 'damage_usd': 2_900_000,
406
+ 'rain_inches': 3.2,
407
+ 'description': 'Rural agricultural flooding event.',
408
+ 'impact_details': 'Crop damage, farm equipment loss',
409
+ 'research_significance': 'Agricultural impact assessment',
410
+ 'tribal_impact': 'Tribal agricultural operations affected',
411
+ 'data_source': 'Oklahoma Department of Agriculture'
412
+ },
413
+ # 2019 Major Events
414
+ {
415
+ 'date': '2019-05-22',
416
+ 'county': 'Tulsa',
417
+ 'location': 'Arkansas River corridor',
418
+ 'type': 'River Flood',
419
+ 'source': 'Record Dam Release - Keystone Dam',
420
+ 'fatalities': 0,
421
+ 'injuries': 3,
422
+ 'damage_usd': 63_500_000,
423
+ 'rain_inches': 15.2,
424
+ 'description': 'Historic flooding from record Keystone Dam releases.',
425
+ 'impact_details': 'Mandatory evacuations of 2,400 people, levee failures',
426
+ 'research_significance': 'Largest Arkansas River flood since 1986',
427
+ 'tribal_impact': 'Muscogee Creek Nation riverside facilities evacuated',
428
+ 'data_source': 'US Army Corps of Engineers'
429
+ },
430
+ {
431
+ 'date': '2019-05-23',
432
+ 'county': 'Muskogee',
433
+ 'location': 'Arkansas River - Muskogee',
434
+ 'type': 'River Flood',
435
+ 'source': 'Continued Arkansas River Flooding',
436
+ 'fatalities': 0,
437
+ 'injuries': 2,
438
+ 'damage_usd': 45_000_000,
439
+ 'rain_inches': 12.8,
440
+ 'description': 'Downstream impacts from Tulsa flooding.',
441
+ 'impact_details': 'Historic downtown flooding, tribal headquarters evacuated',
442
+ 'research_significance': 'Downstream amplification effects',
443
+ 'tribal_impact': 'Muscogee Creek Nation headquarters severely flooded',
444
+ 'data_source': 'Muscogee Creek Nation Emergency Management'
445
+ },
446
+ {
447
+ 'date': '2019-06-02',
448
+ 'county': 'Creek',
449
+ 'location': 'Arkansas River basin',
450
+ 'type': 'River Flood',
451
+ 'source': 'Extended Arkansas River Flooding',
452
+ 'fatalities': 0,
453
+ 'injuries': 1,
454
+ 'damage_usd': 28_700_000,
455
+ 'rain_inches': 10.1,
456
+ 'description': 'Extended flooding impacts on Creek County.',
457
+ 'impact_details': 'Prolonged evacuation, agricultural losses',
458
+ 'research_significance': 'Extended flood duration impacts',
459
+ 'tribal_impact': 'Muscogee Creek agricultural lands flooded',
460
+ 'data_source': 'Creek County Emergency Management'
461
+ },
462
+ # Additional Historical Events
463
+ {
464
+ 'date': '2018-08-15',
465
+ 'county': 'Oklahoma',
466
+ 'location': 'Oklahoma City',
467
+ 'type': 'Flash Flood',
468
+ 'source': 'Severe Thunderstorms',
469
+ 'fatalities': 0,
470
+ 'injuries': 6,
471
+ 'damage_usd': 14_200_000,
472
+ 'rain_inches': 5.9,
473
+ 'description': 'Urban flash flooding during peak summer.',
474
+ 'impact_details': 'Heat-related complications, infrastructure stress',
475
+ 'research_significance': 'Summer urban flood patterns',
476
+ 'tribal_impact': 'Limited tribal impact',
477
+ 'data_source': 'Oklahoma City Emergency Management'
478
+ },
479
+ {
480
+ 'date': '2017-05-10',
481
+ 'county': 'Cleveland',
482
+ 'location': 'Norman',
483
+ 'type': 'Flash Flood',
484
+ 'source': 'Spring Storm System',
485
+ 'fatalities': 0,
486
+ 'injuries': 3,
487
+ 'damage_usd': 8_900_000,
488
+ 'rain_inches': 4.7,
489
+ 'description': 'Spring flooding in Norman university area.',
490
+ 'impact_details': 'University campus impacts, student evacuations',
491
+ 'research_significance': 'University emergency response patterns',
492
+ 'tribal_impact': 'No significant tribal impact',
493
+ 'data_source': 'University of Oklahoma'
494
+ },
495
+ {
496
+ 'date': '2016-06-25',
497
+ 'county': 'Grady',
498
+ 'location': 'Chickasha area',
499
+ 'type': 'Flash Flood',
500
+ 'source': 'Severe Weather',
501
+ 'fatalities': 0,
502
+ 'injuries': 1,
503
+ 'damage_usd': 5_600_000,
504
+ 'rain_inches': 4.2,
505
+ 'description': 'Rural flooding with infrastructure impacts.',
506
+ 'impact_details': 'Rural road damage, bridge impacts',
507
+ 'research_significance': 'Rural infrastructure vulnerability',
508
+ 'tribal_impact': 'Tribal roadway access affected',
509
+ 'data_source': 'Grady County Emergency Management'
510
+ },
511
+ {
512
+ 'date': '2015-05-25',
513
+ 'county': 'Oklahoma',
514
+ 'location': 'Oklahoma City',
515
+ 'type': 'Flash Flood',
516
+ 'source': 'Memorial Day Weekend Storms',
517
+ 'fatalities': 2,
518
+ 'injuries': 12,
519
+ 'damage_usd': 18_000_000,
520
+ 'rain_inches': 7.5,
521
+ 'description': 'Memorial Day weekend flooding from slow-moving storms.',
522
+ 'impact_details': 'Holiday weekend response challenges, 450 homes damaged',
523
+ 'research_significance': 'Seasonal flood vulnerability during holiday periods',
524
+ 'tribal_impact': 'Limited tribal impact',
525
+ 'data_source': 'Oklahoma City Emergency Management'
526
+ },
527
+ {
528
+ 'date': '2015-10-03',
529
+ 'county': 'Tulsa',
530
+ 'location': 'Tulsa Metro',
531
+ 'type': 'Flash Flood',
532
+ 'source': 'Fall Storm System',
533
+ 'fatalities': 0,
534
+ 'injuries': 2,
535
+ 'damage_usd': 6_800_000,
536
+ 'rain_inches': 3.8,
537
+ 'description': 'Fall flooding event in Tulsa metro.',
538
+ 'impact_details': 'Urban drainage overwhelmed',
539
+ 'research_significance': 'Fall flood patterns',
540
+ 'tribal_impact': 'Creek Nation facilities minor impact',
541
+ 'data_source': 'Tulsa Emergency Management'
542
+ }
543
+ ]
544
+
545
+ # Calculate severity and damage classification
546
+ for event in events:
547
+ event['severity_level'] = calculate_severity(event['damage_usd'], event['fatalities'], event['injuries'])
548
+ event['damage_classification'] = classify_damage(event['damage_usd'])
549
+
550
+ return pd.DataFrame(events)
551
+
552
+ # ===================================
553
+ # ANALYSIS FUNCTIONS
554
+ # ===================================
555
+ def mann_kendall_test(data):
556
+ """Perform Mann-Kendall trend test"""
557
+ n = len(data)
558
+ S = 0
559
+
560
+ for i in range(n-1):
561
+ for j in range(i+1, n):
562
+ if data[j] > data[i]:
563
+ S += 1
564
+ elif data[j] < data[i]:
565
+ S -= 1
566
+
567
+ var_s = n * (n - 1) * (2 * n + 5) / 18
568
+
569
+ if S > 0:
570
+ Z = (S - 1) / np.sqrt(var_s)
571
+ elif S < 0:
572
+ Z = (S + 1) / np.sqrt(var_s)
573
+ else:
574
+ Z = 0
575
+
576
+ p_value = 2 * (1 - stats.norm.cdf(abs(Z)))
577
+ trend = "Increasing" if (p_value < 0.05 and S > 0) else "Decreasing" if (p_value < 0.05 and S < 0) else "No significant trend"
578
+
579
+ return S, Z, p_value, trend
580
+
581
+ def create_research_insights():
582
+ """Display key research findings"""
583
+ st.markdown('<div class="insight-box">', unsafe_allow_html=True)
584
+ st.markdown("### πŸŽ“ **Key Research Findings from Oklahoma Flood Studies**")
585
+
586
+ col1, col2 = st.columns(2)
587
+
588
+ with col1:
589
+ st.markdown("""
590
+ **Climate Change Projections (2024 Study):**
591
+ - Native Americans face **68% higher** heavy rainfall risks
592
+ - **64% higher** 2-year flooding frequency
593
+ - **64% higher** flash flooding risks by 2090
594
+ - 4-inch rainfall events expected to **quadruple by 2090**
595
+
596
+ **Historical Analysis (USGS 1964-2024):**
597
+ - Four distinct flood regions in Oklahoma
598
+ - Arkansas River system most vulnerable
599
+ - Urban development increases flash flood risk by 40-60%
600
+ """)
601
+
602
+ with col2:
603
+ st.markdown("""
604
+ **Tribal Nations Vulnerability:**
605
+ - 39 tribal nations face elevated flood risk
606
+ - Muscogee Creek Nation most exposed to river flooding
607
+ - Traditional knowledge integration needed
608
+
609
+ **Economic Impact Patterns:**
610
+ - 2019 Arkansas River flooding: **$3.4-3.7 billion** statewide
611
+ - Agricultural losses: **20% wheat harvest reduction**
612
+ - Infrastructure age correlates with damage severity
613
+ """)
614
+
615
+ st.markdown('</div>', unsafe_allow_html=True)
616
+
617
+ def create_temporal_analysis(df):
618
+ """Create temporal analysis visualizations"""
619
+ st.markdown('<h2 class="sub-header">πŸ“… Advanced Temporal Analysis</h2>', unsafe_allow_html=True)
620
+
621
+ # Prepare data
622
+ df['month'] = df['date'].dt.month
623
+ df['season'] = df['month'].map({
624
+ 12: 'Winter', 1: 'Winter', 2: 'Winter',
625
+ 3: 'Spring', 4: 'Spring', 5: 'Spring',
626
+ 6: 'Summer', 7: 'Summer', 8: 'Summer',
627
+ 9: 'Fall', 10: 'Fall', 11: 'Fall'
628
+ })
629
+
630
+ # Statistical analysis
631
+ annual_counts = df.groupby('year').size()
632
+ annual_damages = df.groupby('year')['damage_usd'].sum()
633
+
634
+ S_count, Z_count, p_count, trend_count = mann_kendall_test(annual_counts.values)
635
+ S_damage, Z_damage, p_damage, trend_damage = mann_kendall_test(annual_damages.values)
636
+
637
+ # Display statistics
638
+ st.markdown('<div class="statistical-box">', unsafe_allow_html=True)
639
+ st.markdown("### πŸ“Š **Statistical Temporal Insights**")
640
+
641
+ col1, col2 = st.columns(2)
642
+
643
+ with col1:
644
+ st.markdown(f"""
645
+ **Flood Frequency Trend (Mann-Kendall Test):**
646
+ - **Trend:** {trend_count}
647
+ - **Z-statistic:** {Z_count:.3f}
648
+ - **P-value:** {p_count:.3f}
649
+ - **Significant:** {'Yes' if p_count < 0.05 else 'No'}
650
+ """)
651
+
652
+ with col2:
653
+ st.markdown(f"""
654
+ **Economic Damage Trend (Mann-Kendall Test):**
655
+ - **Trend:** {trend_damage}
656
+ - **Z-statistic:** {Z_damage:.3f}
657
+ - **P-value:** {p_damage:.3f}
658
+ - **Significant:** {'Yes' if p_damage < 0.05 else 'No'}
659
+ """)
660
+
661
+ st.markdown('</div>', unsafe_allow_html=True)
662
+
663
+ # Create visualizations
664
+ fig = make_subplots(
665
+ rows=2, cols=2,
666
+ subplot_titles=('Annual Flood Events', 'Seasonal Distribution', 'Annual Damage', 'Event Types by Year'),
667
+ specs=[[{"secondary_y": False}, {"secondary_y": False}],
668
+ [{"secondary_y": False}, {"secondary_y": False}]]
669
+ )
670
+
671
+ # Annual events
672
+ annual_stats = df.groupby('year').agg({'date': 'count', 'damage_usd': 'sum'}).rename(columns={'date': 'events'})
673
+
674
+ fig.add_trace(
675
+ go.Scatter(x=annual_stats.index, y=annual_stats['events'],
676
+ mode='lines+markers', name='Annual Events',
677
+ line=dict(color='#4299e1', width=3)),
678
+ row=1, col=1
679
+ )
680
+
681
+ # Seasonal distribution
682
+ seasonal_data = df.groupby(['season', 'severity_level']).size().unstack(fill_value=0)
683
+ colors = {'High': '#e53e3e', 'Medium': '#ed8936', 'Low': '#38a169'}
684
+
685
+ for severity in ['High', 'Medium', 'Low']:
686
+ if severity in seasonal_data.columns:
687
+ fig.add_trace(
688
+ go.Bar(x=seasonal_data.index, y=seasonal_data[severity],
689
+ name=f'{severity} Severity', marker_color=colors[severity]),
690
+ row=1, col=2
691
+ )
692
+
693
+ # Annual damage
694
+ fig.add_trace(
695
+ go.Scatter(x=annual_stats.index, y=annual_stats['damage_usd']/1000000,
696
+ mode='lines+markers', name='Annual Damage ($M)',
697
+ line=dict(color='#e53e3e', width=3)),
698
+ row=2, col=1
699
+ )
700
+
701
+ # Event types by year
702
+ type_year = df.groupby(['year', 'type']).size().unstack(fill_value=0)
703
+ for i, event_type in enumerate(type_year.columns):
704
+ fig.add_trace(
705
+ go.Scatter(x=type_year.index, y=type_year[event_type],
706
+ mode='lines+markers', name=event_type),
707
+ row=2, col=2
708
+ )
709
+
710
+ fig.update_layout(height=800, showlegend=True, title_text="Comprehensive Temporal Analysis")
711
+ st.plotly_chart(fig, use_container_width=True)
712
+
713
+ def create_spatial_analysis(df, county_data):
714
+ """Create spatial analysis visualizations"""
715
+ st.markdown('<h2 class="sub-header">πŸ—ΊοΈ Advanced Spatial Analysis</h2>', unsafe_allow_html=True)
716
+
717
+ # County statistics
718
+ county_stats = df.groupby('county').agg({
719
+ 'date': 'count',
720
+ 'damage_usd': ['sum', 'mean'],
721
+ 'fatalities': 'sum',
722
+ 'injuries': 'sum',
723
+ 'severity_level': lambda x: (x == 'High').sum()
724
+ })
725
+
726
+ county_stats.columns = ['events', 'total_damage', 'avg_damage', 'fatalities', 'injuries', 'high_severity']
727
+ county_stats['total_casualties'] = county_stats['fatalities'] + county_stats['injuries']
728
+ county_stats['risk_score'] = (
729
+ county_stats['events'] * 0.3 +
730
+ (county_stats['total_damage'] / 1000000) * 0.3 +
731
+ county_stats['total_casualties'] * 0.2 +
732
+ county_stats['high_severity'] * 0.2
733
+ )
734
+
735
+ # Create visualizations
736
+ fig = make_subplots(
737
+ rows=2, cols=2,
738
+ subplot_titles=('County Event Frequency', 'Economic Impact vs Events', 'Risk Scores', 'County Heatmap'),
739
+ specs=[[{"type": "bar"}, {"type": "scatter"}],
740
+ [{"type": "bar"}, {"type": "heatmap"}]]
741
+ )
742
+
743
+ # County frequency
744
+ fig.add_trace(
745
+ go.Bar(x=[county_data[c]['full_name'] for c in county_stats.index],
746
+ y=county_stats['events'],
747
+ marker_color=county_stats['events'],
748
+ marker_colorscale='Reds',
749
+ name='Events'),
750
+ row=1, col=1
751
+ )
752
+
753
+ # Economic impact scatter
754
+ fig.add_trace(
755
+ go.Scatter(x=county_stats['events'], y=county_stats['total_damage']/1000000,
756
+ mode='markers',
757
+ marker=dict(size=county_stats['high_severity']*5 + 10,
758
+ color=county_stats['risk_score'],
759
+ colorscale='Viridis', showscale=True),
760
+ text=[county_data[c]['full_name'] for c in county_stats.index],
761
+ name='Impact'),
762
+ row=1, col=2
763
+ )
764
+
765
+ # Risk scores
766
+ fig.add_trace(
767
+ go.Bar(x=[county_data[c]['full_name'] for c in county_stats.index],
768
+ y=county_stats['risk_score'],
769
+ marker_color=county_stats['risk_score'],
770
+ marker_colorscale='RdYlBu_r',
771
+ name='Risk Score'),
772
+ row=2, col=1
773
+ )
774
+
775
+ # County heatmap
776
+ heatmap_data = df.pivot_table(index='county', columns='year', values='damage_usd', aggfunc='sum', fill_value=0) / 1000000
777
+ heatmap_data.index = [county_data.get(county, {}).get('full_name', county) for county in heatmap_data.index]
778
+
779
+ fig.add_trace(
780
+ go.Heatmap(z=heatmap_data.values, x=heatmap_data.columns, y=heatmap_data.index,
781
+ colorscale='Reds', colorbar=dict(title="Damage ($M)")),
782
+ row=2, col=2
783
+ )
784
+
785
+ fig.update_layout(height=1000, showlegend=True, title_text="Comprehensive Spatial Analysis")
786
+ st.plotly_chart(fig, use_container_width=True)
787
+
788
+ def create_impact_analysis(df):
789
+ """Create impact and damage analysis"""
790
+ st.markdown('<h2 class="sub-header">πŸ’° Advanced Impact & Damage Analysis</h2>', unsafe_allow_html=True)
791
+
792
+ df['total_casualties'] = df['fatalities'] + df['injuries']
793
+
794
+ # Statistics
795
+ st.markdown('<div class="statistical-box">', unsafe_allow_html=True)
796
+ st.markdown("### πŸ“Š **Statistical Impact Analysis**")
797
+
798
+ col1, col2 = st.columns(2)
799
+
800
+ with col1:
801
+ total_damage = df['damage_usd'].sum()
802
+ mean_damage = df['damage_usd'].mean()
803
+ median_damage = df['damage_usd'].median()
804
+
805
+ st.markdown(f"""
806
+ **Economic Impact:**
807
+ - **Total Damage:** ${total_damage/1000000:.1f} million
808
+ - **Mean per Event:** ${mean_damage/1000000:.2f} million
809
+ - **Median per Event:** ${median_damage/1000000:.2f} million
810
+ """)
811
+
812
+ with col2:
813
+ total_fatalities = df['fatalities'].sum()
814
+ total_injuries = df['injuries'].sum()
815
+ casualty_rate = (total_fatalities + total_injuries) / len(df)
816
+
817
+ st.markdown(f"""
818
+ **Human Impact:**
819
+ - **Total Fatalities:** {total_fatalities}
820
+ - **Total Injuries:** {total_injuries}
821
+ - **Events with Casualties:** {len(df[df['total_casualties'] > 0])}
822
+ - **Average Casualties per Event:** {casualty_rate:.2f}
823
+ """)
824
+
825
+ st.markdown('</div>', unsafe_allow_html=True)
826
+
827
+ # Visualizations
828
+ fig = make_subplots(
829
+ rows=2, cols=2,
830
+ subplot_titles=('Damage vs Casualties', 'Damage Classification', 'Rainfall vs Damage', 'Severity Over Time'),
831
+ specs=[[{"secondary_y": False}, {"type": "pie"}],
832
+ [{"secondary_y": False}, {"secondary_y": False}]]
833
+ )
834
+
835
+ # Damage vs casualties bubble chart
836
+ fig.add_trace(
837
+ go.Scatter(x=df['fatalities'], y=df['damage_usd']/1000000,
838
+ mode='markers',
839
+ marker=dict(size=df['injuries']*3 + 10, color=df['rain_inches'],
840
+ colorscale='Blues', showscale=True),
841
+ text=df['county'] + '<br>' + df['date'].dt.strftime('%Y-%m-%d'),
842
+ name='Events'),
843
+ row=1, col=1
844
+ )
845
+
846
+ # Damage classification pie
847
+ damage_counts = df['damage_classification'].value_counts()
848
+ colors = {'Catastrophic': '#8b0000', 'Major': '#dc143c', 'Moderate': '#ffa500', 'Minor': '#90ee90'}
849
+
850
+ fig.add_trace(
851
+ go.Pie(labels=damage_counts.index, values=damage_counts.values,
852
+ marker_colors=[colors.get(x, '#gray') for x in damage_counts.index]),
853
+ row=1, col=2
854
+ )
855
+
856
+ # Rainfall vs damage
857
+ fig.add_trace(
858
+ go.Scatter(x=df['rain_inches'], y=df['damage_usd']/1000000,
859
+ mode='markers',
860
+ marker=dict(size=df['total_casualties']*5 + 8, color=df['year'],
861
+ colorscale='Viridis'),
862
+ text=df['type'] + '<br>' + df['severity_level'],
863
+ name='Rainfall Impact'),
864
+ row=2, col=1
865
+ )
866
+
867
+ # Severity over time
868
+ severity_evolution = df.groupby(['year', 'severity_level']).size().unstack(fill_value=0)
869
+ colors = {'High': '#e53e3e', 'Medium': '#ed8936', 'Low': '#38a169'}
870
+
871
+ for severity in ['High', 'Medium', 'Low']:
872
+ if severity in severity_evolution.columns:
873
+ fig.add_trace(
874
+ go.Scatter(x=severity_evolution.index, y=severity_evolution[severity],
875
+ mode='lines+markers', name=f'{severity} Severity',
876
+ line=dict(color=colors[severity], width=3)),
877
+ row=2, col=2
878
+ )
879
+
880
+ fig.update_layout(height=1000, showlegend=True, title_text="Advanced Impact Analysis")
881
+ st.plotly_chart(fig, use_container_width=True)
882
+
883
+ def create_probability_analysis(df):
884
+ """Create probability and risk analysis"""
885
+ st.markdown('<h2 class="sub-header">πŸ“Š Probability & Risk Analysis</h2>', unsafe_allow_html=True)
886
+
887
+ # Calculate return periods
888
+ annual_damages = df.groupby('year')['damage_usd'].sum().values
889
+
890
+ if len(annual_damages) > 0:
891
+ sorted_damages = np.sort(annual_damages)[::-1]
892
+ n = len(sorted_damages)
893
+ ranks = np.arange(1, n + 1)
894
+ exceedance_prob = ranks / (n + 1)
895
+ return_periods = 1 / exceedance_prob
896
+
897
+ # Statistics
898
+ st.markdown('<div class="statistical-box">', unsafe_allow_html=True)
899
+ st.markdown("### 🎯 **Probability Analysis Results**")
900
+
901
+ col1, col2 = st.columns(2)
902
+
903
+ with col1:
904
+ thresholds = [1e6, 5e6, 10e6, 25e6, 50e6]
905
+ st.markdown("**Damage Threshold Probabilities:**")
906
+ for threshold in thresholds:
907
+ exceedances = len(df[df['damage_usd'] >= threshold])
908
+ prob = exceedances / len(df)
909
+ if prob > 0:
910
+ ret_period = 1 / prob
911
+ st.markdown(f"- ${threshold/1e6:.0f}M+: {prob:.3f} ({ret_period:.1f} year return)")
912
+
913
+ with col2:
914
+ damage_mean = df['damage_usd'].mean()
915
+ damage_std = df['damage_usd'].std()
916
+ ci_lower = damage_mean - 1.96 * (damage_std / np.sqrt(len(df)))
917
+ ci_upper = damage_mean + 1.96 * (damage_std / np.sqrt(len(df)))
918
+
919
+ st.markdown(f"""
920
+ **Statistical Confidence Intervals:**
921
+ - **Mean Damage:** ${damage_mean/1e6:.2f}M
922
+ - **95% CI Lower:** ${ci_lower/1e6:.2f}M
923
+ - **95% CI Upper:** ${ci_upper/1e6:.2f}M
924
+ """)
925
+
926
+ st.markdown('</div>', unsafe_allow_html=True)
927
+
928
+ # Visualizations
929
+ fig = make_subplots(
930
+ rows=2, cols=2,
931
+ subplot_titles=('Flood Frequency Curve', 'Exceedance Probability', 'Annual Damage Confidence', 'County Risk Index'),
932
+ specs=[[{"secondary_y": False}, {"secondary_y": False}],
933
+ [{"secondary_y": False}, {"secondary_y": False}]]
934
+ )
935
+
936
+ # Flood frequency curve
937
+ if len(annual_damages) > 0:
938
+ fig.add_trace(
939
+ go.Scatter(x=return_periods, y=sorted_damages/1000000,
940
+ mode='lines+markers', name='Frequency Curve',
941
+ line=dict(color='#e53e3e', width=3)),
942
+ row=1, col=1
943
+ )
944
+
945
+ # Exceedance probability
946
+ damage_thresholds = np.linspace(df['damage_usd'].min(), df['damage_usd'].max(), 100)
947
+ exceedance_probs = [len(df[df['damage_usd'] >= threshold]) / len(df) for threshold in damage_thresholds]
948
+
949
+ fig.add_trace(
950
+ go.Scatter(x=damage_thresholds/1000000, y=np.array(exceedance_probs)*100,
951
+ mode='lines', name='Exceedance Probability',
952
+ line=dict(color='#ed8936', width=3)),
953
+ row=1, col=2
954
+ )
955
+
956
+ # Annual damage with confidence intervals
957
+ years = sorted(df['year'].unique())
958
+ annual_means = []
959
+ annual_stds = []
960
+
961
+ for year in years:
962
+ year_data = df[df['year'] == year]['damage_usd']
963
+ annual_means.append(year_data.mean() if len(year_data) > 0 else 0)
964
+ annual_stds.append(year_data.std() if len(year_data) > 1 else 0)
965
+
966
+ annual_means = np.array(annual_means)
967
+ annual_stds = np.array(annual_stds)
968
+ upper_bound = annual_means + 1.96 * annual_stds
969
+ lower_bound = np.maximum(annual_means - 1.96 * annual_stds, 0)
970
+
971
+ fig.add_trace(
972
+ go.Scatter(x=years, y=annual_means/1000000,
973
+ mode='lines+markers', name='Mean Annual Damage',
974
+ line=dict(color='#4299e1')),
975
+ row=2, col=1
976
+ )
977
+
978
+ fig.add_trace(
979
+ go.Scatter(x=years + years[::-1],
980
+ y=np.concatenate([upper_bound, lower_bound[::-1]])/1000000,
981
+ fill='toself', fillcolor='rgba(66, 153, 225, 0.3)',
982
+ line=dict(color='rgba(255,255,255,0)'),
983
+ name='95% CI'),
984
+ row=2, col=1
985
+ )
986
+
987
+ # County risk index
988
+ county_risk = df.groupby('county').agg({
989
+ 'damage_usd': ['mean', 'count'],
990
+ 'fatalities': 'sum',
991
+ 'injuries': 'sum'
992
+ })
993
+
994
+ county_risk.columns = ['mean_damage', 'event_count', 'fatalities', 'injuries']
995
+ county_risk['risk_index'] = (
996
+ county_risk['mean_damage'] * county_risk['event_count'] *
997
+ (1 + county_risk['fatalities'] + county_risk['injuries'])
998
+ ) / 1000000
999
+
1000
+ fig.add_trace(
1001
+ go.Bar(x=county_risk.index, y=county_risk['risk_index'],
1002
+ marker_color=county_risk['risk_index'],
1003
+ marker_colorscale='Reds', name='Risk Index'),
1004
+ row=2, col=2
1005
+ )
1006
+
1007
+ fig.update_layout(height=1000, showlegend=True, title_text="Advanced Probability Analysis")
1008
+ fig.update_xaxes(title_text="Return Period (Years)", row=1, col=1, type="log")
1009
+ fig.update_yaxes(title_text="Damage ($M)", row=1, col=1)
1010
+ st.plotly_chart(fig, use_container_width=True)
1011
+
1012
+ def create_comparative_analysis(df, county_data):
1013
+ """Create comparative analysis"""
1014
+ st.markdown('<h2 class="sub-header">πŸ”„ Comparative Analysis</h2>', unsafe_allow_html=True)
1015
+
1016
+ # Period comparison
1017
+ period1 = df[df['year'] <= 2018]
1018
+ period2 = df[df['year'] >= 2019]
1019
+
1020
+ st.markdown('<div class="statistical-box">', unsafe_allow_html=True)
1021
+ st.markdown("### πŸ“Š **Period Comparison (2015-2018 vs 2019-2025)**")
1022
+
1023
+ col1, col2, col3 = st.columns(3)
1024
+
1025
+ with col1:
1026
+ p1_events = len(period1)
1027
+ p2_events = len(period2)
1028
+ event_change = ((p2_events - p1_events) / p1_events * 100) if p1_events > 0 else 0
1029
+
1030
+ st.markdown(f"""
1031
+ **Event Frequency:**
1032
+ - **2015-2018:** {p1_events} events
1033
+ - **2019-2025:** {p2_events} events
1034
+ - **Change:** {event_change:+.1f}%
1035
+ """)
1036
+
1037
+ with col2:
1038
+ p1_damage = period1['damage_usd'].sum()
1039
+ p2_damage = period2['damage_usd'].sum()
1040
+ damage_change = ((p2_damage - p1_damage) / p1_damage * 100) if p1_damage > 0 else 0
1041
+
1042
+ st.markdown(f"""
1043
+ **Economic Impact:**
1044
+ - **Period 1:** ${p1_damage/1e6:.1f}M
1045
+ - **Period 2:** ${p2_damage/1e6:.1f}M
1046
+ - **Change:** {damage_change:+.1f}%
1047
+ """)
1048
+
1049
+ with col3:
1050
+ p1_casualties = period1['fatalities'].sum() + period1['injuries'].sum()
1051
+ p2_casualties = period2['fatalities'].sum() + period2['injuries'].sum()
1052
+ casualty_change = ((p2_casualties - p1_casualties) / p1_casualties * 100) if p1_casualties > 0 else 0
1053
+
1054
+ st.markdown(f"""
1055
+ **Human Impact:**
1056
+ - **Period 1:** {p1_casualties} casualties
1057
+ - **Period 2:** {p2_casualties} casualties
1058
+ - **Change:** {casualty_change:+.1f}%
1059
+ """)
1060
+
1061
+ st.markdown('</div>', unsafe_allow_html=True)
1062
+
1063
+ # Visualizations
1064
+ fig = make_subplots(
1065
+ rows=2, cols=2,
1066
+ subplot_titles=('Period Comparison', 'County Rankings', 'Seasonal Matrix', 'Tribal vs Non-Tribal'),
1067
+ specs=[[{"secondary_y": False}, {"secondary_y": False}],
1068
+ [{"type": "heatmap"}, {"secondary_y": False}]]
1069
+ )
1070
+
1071
+ # Period comparison
1072
+ comparison_data = {
1073
+ 'Metric': ['Events', 'Avg Damage ($M)', 'High Severity', 'Casualties'],
1074
+ 'Period_1': [p1_events, period1['damage_usd'].mean()/1e6,
1075
+ len(period1[period1['severity_level'] == 'High']), p1_casualties],
1076
+ 'Period_2': [p2_events, period2['damage_usd'].mean()/1e6,
1077
+ len(period2[period2['severity_level'] == 'High']), p2_casualties]
1078
+ }
1079
+
1080
+ fig.add_trace(
1081
+ go.Bar(x=comparison_data['Metric'], y=comparison_data['Period_1'],
1082
+ name='2015-2018', marker_color='#4299e1'),
1083
+ row=1, col=1
1084
+ )
1085
+
1086
+ fig.add_trace(
1087
+ go.Bar(x=comparison_data['Metric'], y=comparison_data['Period_2'],
1088
+ name='2019-2025', marker_color='#e53e3e'),
1089
+ row=1, col=1
1090
+ )
1091
+
1092
+ # County rankings
1093
+ county_rankings = df.groupby('county').agg({
1094
+ 'damage_usd': 'sum',
1095
+ 'fatalities': 'sum',
1096
+ 'injuries': 'sum'
1097
+ })
1098
+
1099
+ county_rankings['total_impact'] = (
1100
+ county_rankings['damage_usd']/1e6 +
1101
+ county_rankings['fatalities']*10 +
1102
+ county_rankings['injuries']*5
1103
+ )
1104
+ county_rankings = county_rankings.sort_values('total_impact', ascending=True)
1105
+
1106
+ fig.add_trace(
1107
+ go.Bar(x=county_rankings['total_impact'],
1108
+ y=[county_data[c]['full_name'] for c in county_rankings.index],
1109
+ orientation='h', marker_color=county_rankings['total_impact'],
1110
+ marker_colorscale='Reds', name='Impact Score'),
1111
+ row=1, col=2
1112
+ )
1113
+
1114
+ # Seasonal matrix
1115
+ seasonal_matrix = df.groupby(['season', 'year']).size().unstack(fill_value=0)
1116
+
1117
+ fig.add_trace(
1118
+ go.Heatmap(z=seasonal_matrix.values, x=seasonal_matrix.columns,
1119
+ y=seasonal_matrix.index, colorscale='Blues'),
1120
+ row=2, col=1
1121
+ )
1122
+
1123
+ # Tribal vs non-tribal comparison
1124
+ tribal_events = df[df['tribal_impact'].str.contains('Nation|Tribe', na=False)]
1125
+ non_tribal_events = df[~df['tribal_impact'].str.contains('Nation|Tribe', na=False)]
1126
+
1127
+ tribal_comparison = {
1128
+ 'Category': ['Events', 'Avg Damage ($M)', 'Avg Casualties'],
1129
+ 'Tribal': [len(tribal_events),
1130
+ tribal_events['damage_usd'].mean()/1e6 if len(tribal_events) > 0 else 0,
1131
+ (tribal_events['fatalities'].sum() + tribal_events['injuries'].sum())/len(tribal_events) if len(tribal_events) > 0 else 0],
1132
+ 'Non_Tribal': [len(non_tribal_events),
1133
+ non_tribal_events['damage_usd'].mean()/1e6 if len(non_tribal_events) > 0 else 0,
1134
+ (non_tribal_events['fatalities'].sum() + non_tribal_events['injuries'].sum())/len(non_tribal_events) if len(non_tribal_events) > 0 else 0]
1135
+ }
1136
+
1137
+ fig.add_trace(
1138
+ go.Bar(x=tribal_comparison['Category'], y=tribal_comparison['Tribal'],
1139
+ name='Tribal Areas', marker_color='#8b5a3c'),
1140
+ row=2, col=2
1141
+ )
1142
+
1143
+ fig.add_trace(
1144
+ go.Bar(x=tribal_comparison['Category'], y=tribal_comparison['Non_Tribal'],
1145
+ name='Non-Tribal Areas', marker_color='#4299e1'),
1146
+ row=2, col=2
1147
+ )
1148
+
1149
+ fig.update_layout(height=1000, showlegend=True, title_text="Comprehensive Comparative Analysis")
1150
+ st.plotly_chart(fig, use_container_width=True)
1151
+
1152
+ def create_tribal_analysis(df, county_data):
1153
+ """Create tribal nations impact analysis"""
1154
+ st.markdown('<h2 class="sub-header">πŸ›οΈ Tribal Nations Impact Analysis</h2>', unsafe_allow_html=True)
1155
+
1156
+ # Filter tribal events
1157
+ tribal_events = df[df['tribal_impact'].str.contains('Nation|Tribe', na=False)]
1158
+
1159
+ if len(tribal_events) > 0:
1160
+ st.markdown('<div class="insight-box">', unsafe_allow_html=True)
1161
+ st.markdown("### πŸ›οΈ **Tribal Vulnerability Research**")
1162
+
1163
+ col1, col2 = st.columns(2)
1164
+
1165
+ with col1:
1166
+ total_tribal_damage = tribal_events['damage_usd'].sum()
1167
+ affected_nations = set()
1168
+ for _, event in tribal_events.iterrows():
1169
+ county_info = county_data.get(event['county'], {})
1170
+ tribal_nations = county_info.get('tribal_nations', [])
1171
+ affected_nations.update(tribal_nations)
1172
+
1173
+ st.markdown(f"""
1174
+ **Tribal Impact Statistics:**
1175
+ - **Events Affecting Tribal Lands:** {len(tribal_events)}
1176
+ - **Total Damage:** ${total_tribal_damage/1000000:.1f} million
1177
+ - **Tribal Nations Affected:** {len(affected_nations)}
1178
+ - **Average per Event:** ${total_tribal_damage/len(tribal_events)/1000000:.2f}M
1179
+ """)
1180
+
1181
+ with col2:
1182
+ st.markdown("""
1183
+ **Research Validation:**
1184
+ - Native Americans face 64-68% higher flood risks
1185
+ - Climate projections confirm disproportionate impacts
1186
+ - Traditional knowledge integration needed
1187
+ - Enhanced emergency preparedness required
1188
+ """)
1189
+
1190
+ st.markdown('</div>', unsafe_allow_html=True)
1191
+
1192
+ # Tribal analysis chart
1193
+ fig = go.Figure()
1194
+
1195
+ tribal_county_data = tribal_events.groupby('county').agg({
1196
+ 'damage_usd': 'sum',
1197
+ 'fatalities': 'sum',
1198
+ 'injuries': 'sum'
1199
+ })
1200
+
1201
+ fig.add_trace(
1202
+ go.Bar(x=[county_data[c]['full_name'] for c in tribal_county_data.index],
1203
+ y=tribal_county_data['damage_usd']/1000000,
1204
+ marker_color='#8b5a3c',
1205
+ name='Tribal Area Damage ($M)')
1206
+ )
1207
+
1208
+ fig.update_layout(
1209
+ title="Flood Damage in Counties with Tribal Communities",
1210
+ xaxis_title="County",
1211
+ yaxis_title="Damage ($M)",
1212
+ height=400
1213
+ )
1214
+
1215
+ st.plotly_chart(fig, use_container_width=True)
1216
+
1217
+ def create_interactive_map(county_data, flood_df):
1218
+ """Create interactive flood map"""
1219
+ center_lat, center_lon = 35.5, -97.5
1220
+ m = folium.Map(location=[center_lat, center_lon], zoom_start=7)
1221
+
1222
+ # Add county markers
1223
+ for county, info in county_data.items():
1224
+ county_events = flood_df[flood_df['county'] == county]
1225
+
1226
+ if len(county_events) == 0:
1227
+ continue
1228
+
1229
+ event_count = len(county_events)
1230
+ total_damage = county_events['damage_usd'].sum() / 1000000
1231
+
1232
+ severity_colors = {'High': 'red', 'Medium': 'orange', 'Low': 'green'}
1233
+ color = severity_colors.get(info['severity_level'], 'gray')
1234
+
1235
+ popup_html = f"""
1236
+ <div style="font-family: Arial; width: 300px;">
1237
+ <h3>{info['full_name']}</h3>
1238
+ <p><b>Population:</b> {info['population']:,}</p>
1239
+ <p><b>Events:</b> {event_count}</p>
1240
+ <p><b>Total Damage:</b> ${total_damage:.1f}M</p>
1241
+ <p><b>Risk Level:</b> {info['severity_level']}</p>
1242
+ <p><b>Research Notes:</b> {info['research_notes']}</p>
1243
+ </div>
1244
+ """
1245
+
1246
+ folium.Marker(
1247
+ [info['latitude'], info['longitude']],
1248
+ popup=folium.Popup(popup_html, max_width=350),
1249
+ icon=folium.Icon(color=color)
1250
+ ).add_to(m)
1251
+
1252
+ # Add event markers
1253
+ for _, event in flood_df.iterrows():
1254
+ if event['county'] in county_data:
1255
+ county_info = county_data[event['county']]
1256
+
1257
+ # Small offset for visibility
1258
+ event_lat = county_info['latitude'] + np.random.uniform(-0.05, 0.05)
1259
+ event_lon = county_info['longitude'] + np.random.uniform(-0.05, 0.05)
1260
+
1261
+ severity_colors = {'High': '#8b0000', 'Medium': '#ff8c00', 'Low': '#228b22'}
1262
+ color = severity_colors.get(event['severity_level'], '#708090')
1263
+ radius = {'High': 12, 'Medium': 8, 'Low': 5}.get(event['severity_level'], 5)
1264
+
1265
+ folium.CircleMarker(
1266
+ [event_lat, event_lon],
1267
+ radius=radius,
1268
+ popup=f"{event['date'].strftime('%Y-%m-%d')}: {event['type']}<br>${event['damage_usd']/1e6:.1f}M damage",
1269
+ color=color,
1270
+ fill=True,
1271
+ fillOpacity=0.7
1272
+ ).add_to(m)
1273
+
1274
+ return m
1275
+
1276
+ # ===================================
1277
+ # MAIN APPLICATION
1278
+ # ===================================
1279
+ def main():
1280
+ """Main application function"""
1281
+
1282
+ # Header
1283
+ st.markdown('<h1 class="main-header">🌊 Advanced Oklahoma Flood Research Dashboard</h1>', unsafe_allow_html=True)
1284
+ st.markdown('<p style="text-align: center; font-size: 1.3rem; color: #4a5568; font-style: italic;">Comprehensive Multi-Source Flood Analysis (2015-2025)</p>', unsafe_allow_html=True)
1285
+
1286
+ # Research attribution
1287
+ st.markdown("""
1288
+ **Research Sources:** USGS Oklahoma Flood Database | Native American Climate Study (2024) |
1289
+ Oklahoma Emergency Management | Tribal Nations Reports | US Army Corps of Engineers
1290
+ """)
1291
+
1292
+ # Load data
1293
+ county_data = load_county_data()
1294
+ flood_df = load_flood_data()
1295
+ flood_df['date'] = pd.to_datetime(flood_df['date'])
1296
+ flood_df['year'] = flood_df['date'].dt.year
1297
+
1298
+ # Display research insights
1299
+ create_research_insights()
1300
+
1301
+ # Sidebar filters
1302
+ with st.sidebar:
1303
+ st.header("🎯 Analysis Configuration")
1304
+
1305
+ # County selection
1306
+ county_options = ['All Counties'] + list(county_data.keys())
1307
+ selected_county = st.selectbox("Select County", county_options)
1308
+
1309
+ # Severity filter
1310
+ severity_options = ['All Severities', 'High', 'Medium', 'Low']
1311
+ selected_severity = st.selectbox("Filter by Severity", severity_options)
1312
+
1313
+ # Year range
1314
+ min_year, max_year = int(flood_df['year'].min()), int(flood_df['year'].max())
1315
+ year_range = st.slider("Analysis Period", min_year, max_year, (min_year, max_year))
1316
+
1317
+ # Flood type
1318
+ flood_types = ['All Types'] + list(flood_df['type'].unique())
1319
+ selected_type = st.selectbox("Filter by Type", flood_types)
1320
+
1321
+ # Minimum damage threshold
1322
+ min_damage = st.number_input("Minimum Damage ($)", min_value=0, value=0, step=100000)
1323
+
1324
+ # Research mode
1325
+ research_mode = st.checkbox("Enhanced Research Mode", value=True)
1326
+
1327
+ # Apply filters
1328
+ filtered_df = flood_df.copy()
1329
+
1330
+ if selected_county != 'All Counties':
1331
+ filtered_df = filtered_df[filtered_df['county'] == selected_county]
1332
+
1333
+ if selected_severity != 'All Severities':
1334
+ filtered_df = filtered_df[filtered_df['severity_level'] == selected_severity]
1335
+
1336
+ filtered_df = filtered_df[
1337
+ (filtered_df['year'] >= year_range[0]) &
1338
+ (filtered_df['year'] <= year_range[1])
1339
+ ]
1340
+
1341
+ if selected_type != 'All Types':
1342
+ filtered_df = filtered_df[filtered_df['type'] == selected_type]
1343
+
1344
+ if min_damage > 0:
1345
+ filtered_df = filtered_df[filtered_df['damage_usd'] >= min_damage]
1346
+
1347
+ # Summary metrics
1348
+ st.markdown('<h2 class="sub-header">πŸ“Š Summary Statistics</h2>', unsafe_allow_html=True)
1349
+
1350
+ if not filtered_df.empty:
1351
+ col1, col2, col3, col4, col5, col6 = st.columns(6)
1352
+
1353
+ with col1:
1354
+ st.markdown('<div class="metric-card">', unsafe_allow_html=True)
1355
+ st.metric("Total Events", len(filtered_df))
1356
+ st.markdown("Multi-source validated")
1357
+ st.markdown('</div>', unsafe_allow_html=True)
1358
+
1359
+ with col2:
1360
+ total_damage = filtered_df['damage_usd'].sum()
1361
+ st.markdown('<div class="metric-card">', unsafe_allow_html=True)
1362
+ st.metric("Economic Loss", f"${total_damage/1000000:.1f}M")
1363
+ st.markdown("CPI-adjusted damages")
1364
+ st.markdown('</div>', unsafe_allow_html=True)
1365
+
1366
+ with col3:
1367
+ total_fatalities = filtered_df['fatalities'].sum()
1368
+ st.markdown('<div class="metric-card">', unsafe_allow_html=True)
1369
+ st.metric("Total Fatalities", int(total_fatalities))
1370
+ st.markdown("Human impact measure")
1371
+ st.markdown('</div>', unsafe_allow_html=True)
1372
+
1373
+ with col4:
1374
+ high_severity = len(filtered_df[filtered_df['severity_level'] == 'High'])
1375
+ st.markdown('<div class="metric-card">', unsafe_allow_html=True)
1376
+ st.metric("High Severity Events", high_severity)
1377
+ st.markdown(f"{high_severity/len(filtered_df)*100:.1f}% of total")
1378
+ st.markdown('</div>', unsafe_allow_html=True)
1379
+
1380
+ with col5:
1381
+ tribal_affected = len(filtered_df[filtered_df['tribal_impact'].str.contains('Nation|Tribe', na=False)])
1382
+ st.markdown('<div class="metric-card">', unsafe_allow_html=True)
1383
+ st.metric("Tribal Areas Affected", tribal_affected)
1384
+ st.markdown("Indigenous vulnerability")
1385
+ st.markdown('</div>', unsafe_allow_html=True)
1386
+
1387
+ with col6:
1388
+ avg_frequency = len(filtered_df) / (year_range[1] - year_range[0] + 1) if year_range[1] > year_range[0] else 0
1389
+ st.markdown('<div class="metric-card">', unsafe_allow_html=True)
1390
+ st.metric("Annual Frequency", f"{avg_frequency:.1f}")
1391
+ st.markdown("Events per year")
1392
+ st.markdown('</div>', unsafe_allow_html=True)
1393
+
1394
+ # Interactive Map
1395
+ st.markdown('<h2 class="sub-header">πŸ—ΊοΈ Interactive Flood Analysis Map</h2>', unsafe_allow_html=True)
1396
+
1397
+ if selected_county != 'All Counties':
1398
+ county_info = county_data[selected_county]
1399
+ st.markdown('<div class="insight-box">', unsafe_allow_html=True)
1400
+ st.markdown(f"### πŸ“ **{county_info['full_name']} Analysis**")
1401
+
1402
+ col1, col2, col3 = st.columns(3)
1403
+
1404
+ with col1:
1405
+ county_events = len(flood_df[flood_df['county'] == selected_county])
1406
+ county_damage = flood_df[flood_df['county'] == selected_county]['damage_usd'].sum()
1407
+ st.markdown(f"""
1408
+ **Population:** {county_info['population']:,}
1409
+ **Events:** {county_events}
1410
+ **Total Damage:** ${county_damage/1000000:.1f}M
1411
+ """)
1412
+
1413
+ with col2:
1414
+ st.markdown(f"""
1415
+ **Severity:** {county_info['severity_level']}
1416
+ **Elevation:** {county_info['elevation_ft']:,} ft
1417
+ **Tribal Nations:** {len(county_info['tribal_nations'])}
1418
+ """)
1419
+
1420
+ with col3:
1421
+ high_sev_county = len(flood_df[(flood_df['county'] == selected_county) & (flood_df['severity_level'] == 'High')])
1422
+ st.markdown(f"""
1423
+ **High Severity:** {high_sev_county}
1424
+ **Rivers:** {len(county_info['major_rivers'])}
1425
+ **Risk Factors:** {len(county_info['vulnerability_factors'])}
1426
+ """)
1427
+
1428
+ st.markdown(f"**Research Notes:** {county_info['research_notes']}")
1429
+ st.markdown('</div>', unsafe_allow_html=True)
1430
+
1431
+ # Create and display map
1432
+ flood_map = create_interactive_map(county_data, filtered_df)
1433
+ map_data = st_folium(flood_map, width=700, height=650)
1434
+
1435
+ # Analysis tabs
1436
+ if research_mode:
1437
+ tab1, tab2, tab3, tab4, tab5, tab6, tab7 = st.tabs([
1438
+ "πŸ“… Temporal Analysis",
1439
+ "πŸ—ΊοΈ Spatial Analysis",
1440
+ "πŸ’° Impact Analysis",
1441
+ "πŸ“Š Probability Analysis",
1442
+ "πŸ”„ Comparative Analysis",
1443
+ "πŸ›οΈ Tribal Analysis",
1444
+ "πŸ“‹ Event Records"
1445
+ ])
1446
+ else:
1447
+ tab1, tab2, tab3, tab4 = st.tabs([
1448
+ "πŸ“… Temporal Patterns",
1449
+ "πŸ—ΊοΈ Geographic Analysis",
1450
+ "πŸ’° Economic Impact",
1451
+ "πŸ“‹ Event Records"
1452
+ ])
1453
+
1454
+ with tab1:
1455
+ create_temporal_analysis(filtered_df)
1456
+
1457
+ with tab2:
1458
+ create_spatial_analysis(filtered_df, county_data)
1459
+
1460
+ with tab3:
1461
+ create_impact_analysis(filtered_df)
1462
+
1463
+ if research_mode:
1464
+ with tab4:
1465
+ create_probability_analysis(filtered_df)
1466
+
1467
+ with tab5:
1468
+ create_comparative_analysis(filtered_df, county_data)
1469
+
1470
+ with tab6:
1471
+ create_tribal_analysis(filtered_df, county_data)
1472
+
1473
+ with tab7:
1474
+ display_event_records(filtered_df, county_data)
1475
+ else:
1476
+ with tab4:
1477
+ display_event_records(filtered_df, county_data)
1478
+
1479
+ else:
1480
+ st.warning("⚠️ No flood events match the selected criteria. Please adjust your filters.")
1481
+ st.info("πŸ’‘ Try expanding the year range or selecting 'All Counties' to see more events.")
1482
+
1483
+ def display_event_records(df, county_data):
1484
+ """Display detailed event records"""
1485
+ st.markdown('<h3 class="sub-header">πŸ“‹ Detailed Event Records</h3>', unsafe_allow_html=True)
1486
+
1487
+ if not df.empty:
1488
+ # Sort by research priority
1489
+ display_df = df.copy()
1490
+ display_df['research_priority'] = (
1491
+ (display_df['damage_usd'] / 1e6) * 0.4 +
1492
+ (display_df['fatalities'] * 10) * 0.3 +
1493
+ (display_df['injuries'] * 5) * 0.2 +
1494
+ display_df['severity_level'].map({'High': 10, 'Medium': 5, 'Low': 1}) * 0.1
1495
+ )
1496
+ display_df = display_df.sort_values(['research_priority', 'date'], ascending=[False, False])
1497
+
1498
+ st.markdown(f"### πŸ“Š **Event Database ({len(display_df)} events)**")
1499
+
1500
+ # Display in expandable format
1501
+ for idx, (_, row) in enumerate(display_df.iterrows()):
1502
+ severity_class = f"severity-{row['severity_level'].lower()}"
1503
+
1504
+ with st.expander(
1505
+ f"πŸ“‹ Event #{idx+1}: {row['date'].strftime('%Y-%m-%d')} - "
1506
+ f"{county_data.get(row['county'], {}).get('full_name', row['county'])} - "
1507
+ f"{row['severity_level']} Severity - ${row['damage_usd']/1000000:.1f}M"
1508
+ ):
1509
+ col1, col2 = st.columns([2, 1])
1510
+
1511
+ with col1:
1512
+ st.markdown(f"""
1513
+ **πŸ“ Event Details:**
1514
+ - **Location:** {row['location']}
1515
+ - **Type:** {row['type']}
1516
+ - **Cause:** {row['source']}
1517
+ - **Severity:** {row['severity_level']}
1518
+ - **Damage Class:** {row['damage_classification']}
1519
+ - **Rainfall:** {row['rain_inches']} inches
1520
+
1521
+ **πŸ“Š Impact Assessment:**
1522
+ - **Economic Loss:** ${row['damage_usd']:,}
1523
+ - **Fatalities:** {row['fatalities']}
1524
+ - **Injuries:** {row['injuries']}
1525
+ - **Total Casualties:** {row['fatalities'] + row['injuries']}
1526
+ """)
1527
+
1528
+ with col2:
1529
+ county_info = county_data.get(row['county'], {})
1530
+ st.markdown(f"""
1531
+ **πŸ›οΈ County Context:**
1532
+ - **Population:** {county_info.get('population', 'Unknown'):,}
1533
+ - **Risk Level:** {county_info.get('severity_level', 'Unknown')}
1534
+ - **Elevation:** {county_info.get('elevation_ft', 'Unknown'):,} ft
1535
+ - **Tribal Nations:** {len(county_info.get('tribal_nations', []))}
1536
+ """)
1537
+
1538
+ st.markdown("**πŸ“– Description:**")
1539
+ st.write(row['description'])
1540
+
1541
+ if pd.notna(row.get('impact_details')):
1542
+ st.markdown("**⚠️ Impact Details:**")
1543
+ st.write(row['impact_details'])
1544
+
1545
+ st.markdown("**πŸŽ“ Research Significance:**")
1546
+ st.write(row.get('research_significance', 'Standard flood event analysis'))
1547
+
1548
+ st.markdown("**πŸ›οΈ Tribal Impact:**")
1549
+ st.write(row.get('tribal_impact', 'No specific tribal impacts documented'))
1550
+
1551
+ st.markdown(f"**πŸ“š Data Source:** {row['data_source']}")
1552
+
1553
+ # Data export options
1554
+ st.markdown("### πŸ’Ύ **Data Export Options**")
1555
+
1556
+ col1, col2, col3 = st.columns(3)
1557
+
1558
+ with col1:
1559
+ # CSV export
1560
+ csv_data = display_df[[
1561
+ 'date', 'county', 'type', 'severity_level', 'damage_classification',
1562
+ 'fatalities', 'injuries', 'damage_usd', 'rain_inches', 'data_source'
1563
+ ]].copy()
1564
+
1565
+ csv_data['county_full'] = csv_data['county'].map(
1566
+ lambda x: county_data.get(x, {}).get('full_name', x)
1567
+ )
1568
+ csv_data['date'] = csv_data['date'].dt.strftime('%Y-%m-%d')
1569
+ csv_data['damage_millions'] = csv_data['damage_usd'] / 1000000
1570
+
1571
+ csv_export = csv_data.to_csv(index=False)
1572
+ st.download_button(
1573
+ label="πŸ“Š Download CSV Data",
1574
+ data=csv_export,
1575
+ file_name=f"oklahoma_flood_data_{datetime.now().strftime('%Y%m%d')}.csv",
1576
+ mime="text/csv"
1577
+ )
1578
+
1579
+ with col2:
1580
+ # Summary statistics
1581
+ stats_summary = f"""
1582
+ OKLAHOMA FLOOD RESEARCH - SUMMARY STATISTICS
1583
+ Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
1584
+
1585
+ DATASET OVERVIEW:
1586
+ - Total Events: {len(df)}
1587
+ - Study Period: {df['year'].min()}-{df['year'].max()}
1588
+ - Counties: {df['county'].nunique()}
1589
+
1590
+ ECONOMIC IMPACT:
1591
+ - Total Damage: ${df['damage_usd'].sum()/1000000:.1f} million
1592
+ - Mean per Event: ${df['damage_usd'].mean()/1000000:.2f} million
1593
+ - Median per Event: ${df['damage_usd'].median()/1000000:.2f} million
1594
+
1595
+ HUMAN IMPACT:
1596
+ - Total Fatalities: {df['fatalities'].sum()}
1597
+ - Total Injuries: {df['injuries'].sum()}
1598
+ - Events with Casualties: {len(df[(df['fatalities'] > 0) | (df['injuries'] > 0)])}
1599
+
1600
+ SEVERITY DISTRIBUTION:
1601
+ - High Severity: {len(df[df['severity_level'] == 'High'])} events
1602
+ - Medium Severity: {len(df[df['severity_level'] == 'Medium'])} events
1603
+ - Low Severity: {len(df[df['severity_level'] == 'Low'])} events
1604
+
1605
+ TEMPORAL PATTERNS:
1606
+ - Peak Year: {df['year'].value_counts().index[0]} ({df['year'].value_counts().iloc[0]} events)
1607
+ - Spring Events: {len(df[df['date'].dt.month.isin([3,4,5])])}
1608
+ - Summer Events: {len(df[df['date'].dt.month.isin([6,7,8])])}
1609
+
1610
+ TRIBAL IMPACT:
1611
+ - Tribal Events: {len(df[df['tribal_impact'].str.contains('Nation|Tribe', na=False)])}
1612
+ - Tribal Damage: ${df[df['tribal_impact'].str.contains('Nation|Tribe', na=False)]['damage_usd'].sum()/1000000:.1f}M
1613
+
1614
+ Research validates 2024 climate projections of 64-68% higher flood risks for Native American communities.
1615
+ """
1616
+
1617
+ st.download_button(
1618
+ label="πŸ“ˆ Download Statistics",
1619
+ data=stats_summary,
1620
+ file_name=f"oklahoma_flood_stats_{datetime.now().strftime('%Y%m%d')}.txt",
1621
+ mime="text/plain"
1622
+ )
1623
+
1624
+ with col3:
1625
+ # Research methodology
1626
+ methodology = f"""
1627
+ OKLAHOMA FLOOD RESEARCH METHODOLOGY
1628
+ Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
1629
+
1630
+ RESEARCH FRAMEWORK:
1631
+ Multi-source evidence-based approach combining quantitative flood impact assessment
1632
+ with academic research validation.
1633
+
1634
+ DATA SOURCES:
1635
+ 1. USGS Oklahoma Flood Database (1964-2024)
1636
+ 2. Native American Climate Vulnerability Study (2024)
1637
+ 3. Oklahoma Emergency Management Records
1638
+ 4. Tribal Nations Emergency Reports
1639
+ 5. Federal Agency Records (NOAA, FEMA, USACE)
1640
+
1641
+ SEVERITY CLASSIFICATION:
1642
+ - High: >$10M damage OR >10 casualties OR β‰₯2 fatalities
1643
+ - Medium: $1-10M damage OR 1-10 casualties OR 1-2 fatalities
1644
+ - Low: <$1M damage AND <1 casualty
1645
+
1646
+ DAMAGE CLASSIFICATION:
1647
+ - Catastrophic: >$50M
1648
+ - Major: $10-50M
1649
+ - Moderate: $1-10M
1650
+ - Minor: <$1M
1651
+
1652
+ STATISTICAL METHODS:
1653
+ - Mann-Kendall Trend Test for temporal analysis
1654
+ - Weibull Distribution for return period analysis
1655
+ - Multi-source data validation
1656
+ - County-level spatial aggregation
1657
+
1658
+ QUALITY ASSURANCE:
1659
+ - Cross-validation between independent sources
1660
+ - Statistical outlier detection
1661
+ - Missing data handling protocols
1662
+ - Expert review procedures
1663
+
1664
+ LIMITATIONS:
1665
+ - Temporal scope: 2015-2025 enhanced coverage
1666
+ - Geographic resolution: County-level aggregation
1667
+ - Reporting bias toward higher-impact events
1668
+ - Tribal data limited by sovereignty considerations
1669
+
1670
+ APPLICATIONS:
1671
+ - Climate change impact validation
1672
+ - Emergency management planning
1673
+ - Infrastructure investment prioritization
1674
+ - Tribal nation resilience strategies
1675
+
1676
+ This methodology ensures academic rigor while respecting tribal sovereignty
1677
+ and providing actionable insights for flood risk management.
1678
+ """
1679
+
1680
+ st.download_button(
1681
+ label="πŸ“š Download Methodology",
1682
+ data=methodology,
1683
+ file_name=f"oklahoma_flood_methodology_{datetime.now().strftime('%Y%m%d')}.txt",
1684
+ mime="text/plain"
1685
+ )
1686
+
1687
+ # ===================================
1688
+ # RUN APPLICATION
1689
+ # ===================================
1690
+ if __name__ == "__main__":
1691
+ main()
1692
+
1693
+ # ===================================
1694
+ # FOOTER
1695
+ # ===================================
1696
+ st.markdown("---")
1697
+ st.markdown("""
1698
+ <div style="text-align: center; color: #666; font-size: 0.9rem;">
1699
+ <p><strong>Oklahoma Flood Research Dashboard</strong> | Advanced Multi-Source Analysis</p>
1700
+ <p>Integrating USGS, Climate Science, Emergency Management, and Tribal Nation Data</p>
1701
+ <p>Supporting Evidence-Based Flood Risk Management and Climate Adaptation</p>
1702
+ </div>
1703
+ """, unsafe_allow_html=True)