#%% 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. """ # All code levels defined in our codebase code_levels = ['LC','MC','HC'] # All occupancy types defined in our codebase occupancies = ['Res','Com','Ind','Agri','ResCom','Edu','Hea'] # Continent continents = ['Europe','North America','Central & South America', 'Asia', 'Africa', 'Oceania'] # All typologies defined in our codebase typologies = ['BrCfl','BrCri','BrM','Adb','RCi','StMin'] # flood depths resolution defined in JRC flood_depths = [0,0.5,1,1.5,2,3,4,5,6] # Relative damage corresponding to flood_depths (JRC, ASIA) # Note: ResCom, Edu and Hea is copied from Com. 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 (mode) number of storeys within the JRC empirical data (Asia, Residential) most_common_nstories = 2 # Type I typologies in Figure 2 of Englhardt et al 2019. typeI_typologies= ['Adb','Erth','Inf','M','Re','Wwd'] weak_typologies = ['Adb','StMin','BrM'] # Digitized on JRC flood depths 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): # There don't exist in JRC 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 # Applying Type I in Figure 2 of Englhardt et al 2019. 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 # Create adjuste damage function 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): # TODO: filter out unreasable taxonomies 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 # Save df to Excel filename = 'flood_vulnerability'+str(uuid.uuid4())+'.xlsx' df.to_excel(filename,index=False) return filename # Gradio application 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") # Layout is done, add triggers now 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] ) # Launch the GUI demo.launch()