Flooding_Impact_SLR_Analysis / app_streamlit.py
edwinrajeev's picture
Rename app.py to app_streamlit.py
6bed38d verified
import streamlit as st
import pandas as pd
import numpy as np
from scipy.stats import percentileofscore
import plotly.graph_objects as go
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt
def refine_curve(x, p, num_points=200):
interp_func = interp1d(x, p, kind='cubic')
x_refined = np.linspace(x[0], x[-1], num=num_points)
p_refined = interp_func(x_refined)
return x_refined, p_refined
def calculate_flooding_impact(threshold, slr_interL_20, slr_interH_20, slr_interL_50, slr_interH_50, file):
df_water_levels = pd.read_excel(file)
df_water_levels['t'] = pd.to_datetime(df_water_levels['t'])
df_water_levels['date'] = df_water_levels['t'].dt.date
# Plotting water levels
fig1 = go.Figure()
fig1.add_trace(go.Scatter(x=df_water_levels['t'], y=df_water_levels['v'], mode='lines', name='Water Level', line=dict(color='blue')))
fig1.update_layout(
yaxis=dict(range=[-7, 7], title='Elevation (ft)', showgrid=False),
xaxis=dict(title="Year", showgrid=False),
legend=dict(x=0.02, y=0.98)
)
# Calculate highest water levels and exceedances
highest_water_levels = df_water_levels.groupby('date')['v'].max()
exceedances_by_year = {}
for date, water_level in highest_water_levels.items():
year = date.year
if year in exceedances_by_year:
exceedances_by_year[year].append((date, water_level))
else:
exceedances_by_year[year] = [(date, water_level)]
exd_year = []
num_exd = []
for year, exceedances in exceedances_by_year.items():
num_exceedances = len([exceedance for exceedance in exceedances if exceedance[1] > threshold])
exd_year.append(year)
num_exd.append(num_exceedances)
# Bar plot for exceedances
fig2 = go.Figure(data=[go.Bar(x=exd_year, y=num_exd, marker_color='blue')])
fig2.update_layout(
title='Occurrences of Threshold Value Exceedance for Each Year',
xaxis_title='Year',
yaxis_title='Number of Days of Exceedance',
xaxis=dict(
tickvals=exd_year,
ticktext=[str(year) for year in exd_year],
tickangle=90,
),
)
# Impact Flooding Analysis
surfaceEl = highest_water_levels.tolist()
surfaceEl = [x for x in surfaceEl if not np.isnan(x)]
surfaceEl_SLR_L = [num + slr_interL_20 for num in surfaceEl]
surfaceEl_SLR_H = [num + slr_interH_20 for num in surfaceEl]
surfaceEl_SLR_L_50 = [num + slr_interL_50 for num in surfaceEl]
surfaceEl_SLR_H_50 = [num + slr_interH_50 for num in surfaceEl]
bin_magnitude = 0.2
max_mag = (max(surfaceEl)*10)/10
min_mag = (min(surfaceEl)*10)/10
P = np.arange(min_mag, max_mag + bin_magnitude, bin_magnitude)
p = [percentileofscore(surfaceEl, z)/100 for z in P]
# Calculate P and p for different scenarios
P_slrL, p_slrL = refine_curve(P, [percentileofscore(surfaceEl_SLR_L, z)/100 for z in P])
P_slrH, p_slrH = refine_curve(P, [percentileofscore(surfaceEl_SLR_H, z)/100 for z in P])
P_slrL_50, p_slrL_50 = refine_curve(P, [percentileofscore(surfaceEl_SLR_L_50, z)/100 for z in P])
P_slrH_50, p_slrH_50 = refine_curve(P, [percentileofscore(surfaceEl_SLR_H_50, z)/100 for z in P])
# Calculate days impacted
days_impacted_current = (100 - percentileofscore(surfaceEl, threshold)) * 365 / 100
days_impacted_slrL = (100 - percentileofscore(surfaceEl_SLR_L, threshold)) * 365 / 100
days_impacted_slrH = (100 - percentileofscore(surfaceEl_SLR_H, threshold)) * 365 / 100
days_impacted_slrL_50 = (100 - percentileofscore(surfaceEl_SLR_L_50, threshold)) * 365 / 100
days_impacted_slrH_50 = (100 - percentileofscore(surfaceEl_SLR_H_50, threshold)) * 365 / 100
# Bar plot for SLR
fig3, ax = plt.subplots()
bars = ['2040', '2070']
bar1_min, bar1_max = round(days_impacted_slrL), round(days_impacted_slrH)
bar2_min, bar2_max = round(days_impacted_slrL_50), round(days_impacted_slrH_50)
x = range(len(bars))
ax.bar(x, [bar1_max, bar2_max], alpha=0.7, width=0.4, align='center', label='Intermediate High')
ax.bar(x, [bar1_min, bar2_min], alpha=1, width=0.4, align='center', label='Intermediate Low')
ax.set_xticks(x)
ax.set_xticklabels(bars)
ax.set_ylabel('Days')
ax.set_title('Number of Days of Exceedance with SLR')
ax.set_ylim(0, 365)
ax.legend()
# Plot PDF
fig4 = go.Figure()
fig4.add_trace(go.Scatter(x=P[:-1], y=np.diff(p), mode='lines', name='Current', line_color='green', fill='tozeroy'))
fig4.add_trace(go.Scatter(x=P_slrL[:-1], y=np.diff(p_slrL), mode='lines', name='20 Yr SLR Intermediate Low (IL)', line_color='yellow', fill='tozeroy'))
fig4.add_trace(go.Scatter(x=P_slrH[:-1], y=np.diff(p_slrH), mode='lines', name='20 Yr SLR Intermediate High (IH)', line_color='orange', fill='tozeroy'))
fig4.add_trace(go.Scatter(x=P_slrL_50[:-1], y=np.diff(p_slrL_50), mode='lines', name='50 Yr SLR Intermediate Low (IL)', line_color='pink', fill='tozeroy'))
fig4.add_trace(go.Scatter(x=P_slrH_50[:-1], y=np.diff(p_slrH_50), mode='lines', name='50 Yr SLR Intermediate High (IH)', line_color='red', fill='tozeroy'))
fig4.update_layout(
xaxis_title='Water Level (feet)',
yaxis_title='Probability Density',
title='Impact Flooding (Number of Days Impacted)',
hovermode='x unified',
legend=dict(x=0, y=1),
showlegend=True,
xaxis=dict(showgrid=True),
yaxis=dict(showgrid=True)
)
text_output = (
f"Number of days impacted by flooding (current): {round(days_impacted_current)}\n"
f"Number of days impacted by flooding (20 Year SLR IL): {round(days_impacted_slrL)}\n"
f"Number of days impacted by flooding (20 Year SLR IH): {round(days_impacted_slrH)}\n"
f"Number of days impacted by flooding (50 Year SLR IL): {round(days_impacted_slrL_50)}\n"
f"Number of days impacted by flooding (50 Year SLR IH): {round(days_impacted_slrH_50)}\n"
)
return fig1, fig2, fig3, fig4, text_output
st.title("Flooding Impact Calculator")
st.write("Calculate the impact of flooding based on water level data and sea-level rise. Input the threshold value to determine the number of days flooding can occur due to high tide. For more information, determine SLR values from reliable sources such as IPCC, [NOAA](https://coast.noaa.gov/slr/). Upload the water levels in the provided Excel format.")
threshold = st.number_input("Threshold Value (feet)", value=1.0)
slr_interL_20 = st.number_input("20 YR SLR Intermediate Low (feet)", value=0.5)
slr_interH_20 = st.number_input("20 YR SLR Intermediate High (feet)", value=0.7)
slr_interL_50 = st.number_input("50 YR SLR Intermediate Low (feet)", value=0.7)
slr_interH_50 = st.number_input("50 YR SLR Intermediate High (feet)", value=1.5)
uploaded_file = st.file_uploader("Upload water_levels.xlsx", type="xlsx")
if uploaded_file is not None:
fig1, fig2, fig3, fig4, text_output = calculate_flooding_impact(threshold, slr_interL_20, slr_interH_20, slr_interL_50, slr_interH_50, uploaded_file)
st.plotly_chart(fig1)
st.plotly_chart(fig2)
st.pyplot(fig3)
st.plotly_chart(fig4)
st.text(text_output)