|
|
|
import gradio as gd |
|
import numpy as np |
|
import pandas as pd |
|
import plotly.express as px |
|
import uuid |
|
|
|
info_text = """ |
|
# Flood Vulnerability Generator |
|
This interface is prepared to visualize the flood damage functions defined by JRC and generate flood vulnerability file that can be used in [Tomorrow's Cities Decision Support Environment Web App](https://github.com/TomorrowsCities/tomorrowscities). The raw damage curves are borrowed from [JRC Global Flood Depth Damage Function Database](https://publications.jrc.ec.europa.eu/repository/bitstream/JRC105688/copy_of_global_flood_depth-damage_functions__30102017.xlsx). The following adjustments are done in order: |
|
* The occupancy types of ResCom, Edu, or Hea are not defined in JRC database. Therefore, for these types, occupancy type is assumed to be Com. |
|
* If there is no damage curve defined in JRC for specific continent/occupancy pair, then Global damage curve is used. For instance, there is no curve for commercial (Com) buildings in Africa. In this case, the Global curve for Com is used. See "Damage functions" tab in [JRC Global Flood Depth Damage Function Database](https://publications.jrc.ec.europa.eu/repository/bitstream/JRC105688/copy_of_global_flood_depth-damage_functions__30102017.xlsx). |
|
* Height adjustment: the damage value is multiplied by 2/(number of storeys) when number of storeys is greater than one. |
|
* "Nairobi Patch": when selected, the program uses the Type I curve in [Englhardt et al 2019](https://nhess.copernicus.org/articles/19/1703/2019/nhess-19-1703-2019.pdf) for weak structures (Adb, StMin, BrM) and single-storey buildings in Africa. |
|
|
|
To see the original JRC curves as well as the adjusted versions, play with the continent, occupancy, typology, code level, and number of storeys. The interface will plot original JRC damage curves as well as the adjusted curves. Please notice that code level will not have an effect on damage curves. |
|
|
|
If you would like to generate an excel file containing all adjusted damage functions for all possible combinations except the continent, please click "Generate" button. You will be able to download the continent-specific vulnerability file and use it directly in the [Web App]((https://github.com/TomorrowsCities/tomorrowscities). |
|
|
|
## Changelog |
|
**2024-02-06** (based on Vibek's feedback) |
|
* Damage cap feature is removed as this functionaliy is only meant for monetary calculations which we don't do here. |
|
* Nairobi patch is limited to Africa. |
|
* In addition to Adb, Nairobi patch is also applied to StMin and BrM structures. |
|
* Height adjustment is not applied to single-storey buildigs. |
|
""" |
|
|
|
|
|
code_levels = ['LC','MC','HC'] |
|
|
|
|
|
occupancies = ['Res','Com','Ind','Agri','ResCom','Edu','Hea'] |
|
|
|
|
|
continents = ['Europe','North America','Central & South America', 'Asia', 'Africa', 'Oceania'] |
|
|
|
|
|
typologies = ['BrCfl','BrCri','BrM','Adb','RCi','StMin'] |
|
|
|
|
|
flood_depths = [0,0.5,1,1.5,2,3,4,5,6] |
|
|
|
|
|
|
|
damage_functions = { |
|
'Asia': { |
|
'Res': [0.00, 0.33, 0.49, 0.62, 0.72, 0.87, 0.93, 0.98, 1.00], |
|
'Com': [0.00, 0.38, 0.54, 0.66, 0.76, 0.88, 0.94, 0.98, 1.00], |
|
'Ind': [0.00, 0.28, 0.48, 0.63, 0.72, 0.86, 0.91, 0.96, 1.00], |
|
'Agri': [0.00, 0.14, 0.37, 0.52, 0.56, 0.66, 0.83, 0.99, 1.00], |
|
}, |
|
'Europe': { |
|
'Res': [0.00, 0.25, 0.40, 0.50, 0.60, 0.75, 0.85, 0.95, 1.00], |
|
'Com': [0.00, 0.15, 0.30, 0.45, 0.55, 0.75, 0.90, 1.00, 1.00], |
|
'Ind': [0.00, 0.15, 0.27, 0.40, 0.52, 0.70, 0.85, 1.00, 1.00], |
|
'Agri': [0.00, 0.30, 0.55, 0.65, 0.75, 0.85, 0.95, 1.00, 1.00], |
|
}, |
|
'North America': { |
|
'Res': [0.20, 0.44, 0.58, 0.68, 0.78, 0.85, 0.92, 0.96, 1.00], |
|
'Com': [0.02, 0.24, 0.37, 0.47, 0.55, 0.69, 0.82, 0.91, 1.00], |
|
'Ind': [0.03, 0.32, 0.51, 0.64, 0.74, 0.86, 0.94, 0.98, 1.00], |
|
'Agri': [0.02, 0.27, 0.47, 0.55, 0.60, 0.76, 0.87, 0.95, 1.00], |
|
}, |
|
'Central & South America' : { |
|
'Res': [0.00, 0.49, 0.71, 0.84, 0.95, 0.98, 1.00, 1.00, 1.00], |
|
'Com': [0.00, 0.61, 0.84, 0.92, 0.99, 1.00, 1.00, 1.00, 1.00], |
|
'Ind': [0.00, 0.67, 0.89, 0.95, 1.00, 1.00, 1.00, 1.00, 1.00], |
|
}, |
|
'Africa': { |
|
'Res': [0.00, 0.22, 0.38, 0.53, 0.64, 0.82, 0.90, 0.96, 1.00], |
|
'Ind': [0.00, 0.06, 0.25, 0.40, 0.49, 0.68, 0.92, 1.00, 1.00], |
|
'Agri': [0.00, 0.24, 0.47, 0.74, 0.92, 1.00, 1.00, 1.00, 1.00], |
|
}, |
|
'Oceania': { |
|
'Res': [0.00, 0.48, 0.64, 0.71, 0.79, 0.93, 0.97, 0.98, 1.00], |
|
'Com': [0.00, 0.24, 0.48, 0.67, 0.86, 1.00, 1.00, 1.00, 1.00], |
|
}, |
|
'Global': { |
|
'Com': [0.00, 0.32, 0.51, 0.63, 0.74, 0.86, 0.93, 0.98, 1.00], |
|
'Ind': [0.00, 0.30, 0.48, 0.60, 0.69, 0.82, 0.92, 0.99, 1.00], |
|
'Agri': [0.00, 0.24, 0.47, 0.62, 0.71, 0.82, 0.91, 0.99, 1.00], |
|
} |
|
} |
|
|
|
|
|
most_common_nstories = 2 |
|
|
|
|
|
typeI_typologies= ['Adb','Erth','Inf','M','Re','Wwd'] |
|
weak_typologies = ['Adb','StMin','BrM'] |
|
|
|
|
|
typeI_damage_function = [0,0.49,0.91,1.00,1.00,1.00,1.00,1.00,1] |
|
|
|
def get_damage_function(continent, occupancy, typology, code_level, nstoreys, nairobi_patch): |
|
|
|
if occupancy in ['ResCom','Edu','Hea']: |
|
occupancy = 'Com' |
|
if occupancy in damage_functions[continent].keys(): |
|
jrc_damage = damage_functions[continent][occupancy] |
|
else: |
|
jrc_damage = damage_functions['Global'][occupancy] |
|
|
|
rel_damage = jrc_damage.copy() |
|
|
|
height_adjustment_factor = 2.0/nstoreys if nstoreys > 1 else 1 |
|
|
|
|
|
if nairobi_patch: |
|
if typology in typeI_typologies + weak_typologies and nstoreys == 1 and continent == 'Africa': |
|
rel_damage = typeI_damage_function |
|
height_adjustment_factor = 1 |
|
|
|
max_damage = 1 |
|
|
|
|
|
rel_damage_adjusted = rel_damage.copy() |
|
for idx, damage in enumerate(rel_damage): |
|
rel_damage_adjusted[idx] = min(height_adjustment_factor * damage, max_damage) |
|
|
|
return jrc_damage, rel_damage_adjusted |
|
|
|
|
|
def plot_damage_function(continent, occupancy, typology, code_level, nstoreys, nairobi_patch): |
|
jrc_curve, adjusted_curve = get_damage_function(continent, occupancy, typology, code_level, nstoreys, nairobi_patch) |
|
flood_depths_np = np.array(flood_depths).reshape(-1,1) |
|
rel_damage_np = np.array(jrc_curve).reshape(-1,1) |
|
rel_damage_adjusted_np = np.array(adjusted_curve).reshape(-1,1) |
|
|
|
data_wo_adjustment = pd.DataFrame(np.concatenate([flood_depths_np,rel_damage_np],axis=1), |
|
columns=['water_height','damage']) |
|
data_wo_adjustment['class'] = 'JRC Original' |
|
|
|
data_w_adjustment = pd.DataFrame(np.concatenate([flood_depths_np,rel_damage_adjusted_np],axis=1), |
|
columns=['water_height','damage']) |
|
data_w_adjustment['class'] = 'Adjusted' |
|
|
|
data = pd.concat([data_w_adjustment,data_wo_adjustment]) |
|
|
|
return px.line(data, x="water_height", y="damage", range_y=[0,1], |
|
color='class', symbol='class', markers=True) |
|
|
|
|
|
def generate_excel(continent, nairobi_patch): |
|
hwcolumns = [f"hw{str(hw).replace('.','_')}" for hw in flood_depths] |
|
df = pd.DataFrame(columns=['expstr']+hwcolumns) |
|
for occupancy in occupancies: |
|
for typology in typologies: |
|
for code_level in code_levels: |
|
for nstoreys in range(1,51): |
|
|
|
tax = f'{typology}+{code_level}+{nstoreys}s+{occupancy}' |
|
_, adjusted_curve = get_damage_function(continent, occupancy, typology, code_level, nstoreys, nairobi_patch) |
|
|
|
adjusted_curve_as_text = [f'{c:5.3f}' for c in adjusted_curve] |
|
row = [tax] + adjusted_curve_as_text |
|
df.loc[len(df)] = row |
|
|
|
filename = 'flood_vulnerability'+str(uuid.uuid4())+'.xlsx' |
|
df.to_excel(filename,index=False) |
|
return filename |
|
|
|
|
|
|
|
with gd.Blocks() as demo: |
|
info = gd.Markdown(value=info_text) |
|
with gd.Row(): |
|
continent = gd.Radio(choices=continents, |
|
value=continents[0], |
|
label='Continent') |
|
occupancy = gd.Radio(choices=occupancies, |
|
value=occupancies[0], |
|
label='Occupancy') |
|
typology = gd.Radio(choices=typologies, |
|
value=typologies[0], |
|
label="Typology") |
|
code_level = gd.Radio(choices=code_levels, |
|
value=code_levels[0], |
|
label='Code Level') |
|
nstoreys = gd.Radio(choices=[1,2,3,4,5,6,7,8,9,10], |
|
value=3, |
|
label='Number of storeys') |
|
nairobi_patch = gd.Checkbox(value=False, |
|
label='Apply Nairobi Patch', |
|
info="""If the typology is of weak-type (Adb, StMin, BrM) |
|
,the number of storeys is 1 and the continent is Africa, then use |
|
Type I data in Figure 2 of Englhardt et al 2019. |
|
""") |
|
plot = gd.Plot() |
|
with gd.Row(): |
|
btn = gd.Button(value="Generate Flood Vulnerability File") |
|
file = gd.File(label="Generated File") |
|
|
|
|
|
demo.load(plot_damage_function, |
|
inputs=[continent,occupancy,typology, code_level, nstoreys, nairobi_patch], |
|
outputs=[plot]) |
|
for component in [continent,occupancy, typology, code_level, nstoreys, nairobi_patch]: |
|
component.change(plot_damage_function, |
|
inputs=[continent,occupancy,typology, code_level, nstoreys, nairobi_patch], |
|
outputs=[plot]) |
|
btn.click(generate_excel, inputs=[continent, nairobi_patch],outputs=[file] ) |
|
|
|
|
|
demo.launch() |
|
|