Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Splitting data and helper operations into separate files and avoid unnecessary downloads #37

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 67 additions & 126 deletions tools/code/Floods_Fathom3/GUI_F3.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -12,87 +12,23 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"id": "1411ecc4",
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ab8f861302f54f16a2c160b04b0ef8ec",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"VBox(children=(HTML(value='\\n<div style=\\'\\n background: linear-gradient(to bottom, #003366, transparent);\\…"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"<script>\n",
"document.querySelector('.country-selector-2604615989472').onmouseover = function() {\n",
" document.querySelector('.info-box textarea').value = 'Enter the country name.';\n",
"};\n",
"document.querySelector('.hazard-selector-2604616417968').onmouseover = function() {\n",
" document.querySelector('.info-box textarea').value = 'Select the type of flood hazard.\\nThe DEFENDED option accounts for protection standards set proportional to country GDP; it does not account for geolocated physical defence measures.';\n",
"};\n",
"document.querySelector('.hazard-threshold-slider-2604615988704').onmouseover = function() {\n",
" document.querySelector('.info-box textarea').value = 'Set the minimum hazard threshold, in the unit of the dataset.\\nValues below this threshold will be ignored.';\n",
"};\n",
"document.querySelector('.period-selector-2604616420080').onmouseover = function() {\n",
" document.querySelector('.info-box textarea').value = 'Select the reference time period for the hazard analysis:\\n\\n- Historical baseline: 2020\\n- Future periods: 2030, 2050, 2080';\n",
"};\n",
"document.querySelector('.scenario-selector-2604615988752').onmouseover = function() {\n",
" document.querySelector('.info-box textarea').value = 'Choose the climate scenario for future projections.';\n",
"};\n",
"document.querySelector('.return_periods-selector-2604615989088').onmouseover = function() {\n",
" document.querySelector('.info-box textarea').value = 'Choose the return periods to consider.\\nCtrl + click or drag mouse for multiple choices.\\n\\nReturn period defines the intensity of the hazard in relation to its occurrence probability.\\nWhen using the function approach, the whole range selection is preferred for best results.';\n",
"};\n",
"document.querySelector('.exposure-selector-2604616423536').onmouseover = function() {\n",
" document.querySelector('.info-box textarea').value = 'Select the exposure category on which the risk is calculated.\\nCtrl + click or drag mouse for multiple choices.';\n",
"};\n",
"document.querySelector('.custom-exposure-radio-2604616424880').onmouseover = function() {\n",
" document.querySelector('.info-box textarea').value = 'Choose between default exposure data or custom exposure data provided by the user.\\n\\nDefault data sources are:\\n- Population: WorldPop 2020 (100 m)\\n- Built-up: World Settlement Footprint 2019 (100 m)\\n- Agricolture: ESA World Cover 2019 - Crop area (1 km)';\n",
"};\n",
"document.querySelector('.custom-exposure-textbox-2604616424832').onmouseover = function() {\n",
" document.querySelector('.info-box textarea').value = 'Enter the filename (without extension) of your custom exposure data.\\n- Must be a valid .tif file using CRS:4326\\n- Must be located in the EXP folder. ';\n",
"};\n",
"document.querySelector('.approach-selector-2604615990576').onmouseover = function() {\n",
" document.querySelector('.info-box textarea').value = 'Select the approach for risk classification: Classes or Function.\\n\\n- Function approach is based on default impact functions for each exposure category.\\n- Classes approach measures the average annual exposure to user-defined hazard thresholds. Thresholds must be inserted in incremental order.';\n",
"};\n",
"document.querySelector('.adm-level-selector-2604615990864').onmouseover = function() {\n",
" document.querySelector('.info-box textarea').value = 'Select the administrative level to aggregate and present the results of the analysis.';\n",
"};\n",
"</script>\n"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"import ipywidgets as widgets\n",
"import os\n",
"import requests\n",
"import pandas as pd\n",
"import numpy as np\n",
"import time\n",
"from common import *\n",
"from IPython.display import display, clear_output, HTML\n",
"from PIL import Image as PILImage\n",
"from io import BytesIO\n",
"# from damageFunctions import mortality_factor, damage_factor_builtup, damage_factor_agri\n",
"from runAnalysis import run_analysis, plot_results\n",
"from runAnalysis import run_analysis\n",
"from utils import plot_results\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"\n",
Expand Down Expand Up @@ -142,7 +78,7 @@
" with output:\n",
" output.clear_output()\n",
" selected_country = change['new']\n",
" if selected_country in country_dict:\n",
" if selected_country in country_dict.keys():\n",
" iso_a3 = country_dict[selected_country]\n",
" print(f'Selected Country: {selected_country}, ISO_A3 Code: {iso_a3}')\n",
" else:\n",
Expand All @@ -166,14 +102,17 @@
"], value='FLUVIAL_UNDEFENDED', description='Hazard process:', layout=widgets.Layout(width='400px'), style={'description_width': '150px'})\n",
"hazard_selector_id = f'hazard-selector-{id(hazard_selector)}'\n",
"hazard_selector.add_class(hazard_selector_id)\n",
"\n",
"## Hazard threshold\n",
"hazard_threshold_slider = widgets.IntSlider(value=20, min=0, max=200, description='Hazard threshold:', layout=widgets.Layout(width='420px'), style={'description_width': '150px'})\n",
"hazard_threshold_slider_id = f'hazard-threshold-slider-{id(hazard_threshold_slider)}'\n",
"hazard_threshold_slider.add_class(hazard_threshold_slider_id)\n",
"\n",
"## Period\n",
"period_selector = widgets.Dropdown(options=['2020', '2030', '2050', '2080'], value='2020', description='Hazard reference period:', layout=widgets.Layout(width='400px'), style={'description_width': '150px'})\n",
"period_selector_id = f'period-selector-{id(period_selector)}'\n",
"period_selector.add_class(period_selector_id)\n",
"\n",
"## Scenario\n",
"scenario_selector = widgets.Dropdown(options=[\n",
" ('SSP1-2.6', 'SSP1_2.6'),\n",
Expand All @@ -183,6 +122,7 @@
"], value='SSP3_7.0', description='Climate scenario:', layout=widgets.Layout(width='400px'), style={'description_width': '150px'})\n",
"scenario_selector_id = f'scenario-selector-{id(scenario_selector)}'\n",
"scenario_selector.add_class(scenario_selector_id)\n",
"\n",
"## Hazard return periods\n",
"return_periods_selector = widgets.SelectMultiple(\n",
" options=[5, 10, 20, 50, 100, 200, 500, 1000],\n",
Expand All @@ -203,6 +143,7 @@
"], description='Exposure:', value=['POP'], layout=widgets.Layout(width='400px'), style={'description_width': '150px'})\n",
"exposure_selector_id = f'exposure-selector-{id(exposure_selector)}'\n",
"exposure_selector.add_class(exposure_selector_id)\n",
"\n",
"## Custom exposure\n",
"custom_exposure_container = widgets.VBox([])\n",
"custom_exposure_radio = widgets.RadioButtons(options=['Default exposure', 'Custom exposure'], description='', layout=widgets.Layout(width='400px'))\n",
Expand Down Expand Up @@ -235,7 +176,7 @@
"update_scenario_visibility()\n",
"\n",
"# Function to update custom exposure textboxes\n",
"def update_custom_exposure_textboxes(*args):\n",
"def update_custom_exposure_textboxes():\n",
" custom_exposure_container.children = []\n",
" if custom_exposure_radio.value == 'Custom exposure':\n",
" for exp in exposure_selector.value:\n",
Expand All @@ -261,42 +202,45 @@
"class_edges_table = widgets.VBox()\n",
"\n",
"# For approach = function, preview impact function\n",
"def preview_impact_func(*args):\n",
" if approach_selector.value == 'Function':\n",
" with approach_box:\n",
" clear_output(wait=True) # Clear the previous output\n",
" selected_exposures = exposure_selector.value\n",
" if selected_exposures:\n",
" steps = np.arange(0, 6, 0.1)\n",
" fig, ax = plt.subplots(figsize=(4, 3))\n",
" \n",
" damage_factors = {\n",
" 'POP': mortality_factor,\n",
" 'BU': damage_factor_builtup,\n",
" 'AGR': damage_factor_agri\n",
" }\n",
" \n",
" for exposure in selected_exposures:\n",
" if exposure in damage_factors:\n",
" damage_factor = damage_factors[exposure]\n",
" line, = ax.plot([damage_factor(x) for x in steps], label=exposure)\n",
" else:\n",
" print(f\"Unknown exposure category: {exposure}\")\n",
" \n",
" ax.grid(True)\n",
" ax.legend()\n",
" \n",
" label_steps = range(0, len(steps)+10, 10)\n",
" ax.set_xticks(label_steps)\n",
" ax.set_xticklabels([i / 10 for i in label_steps])\n",
" ax.set_xlabel(\"Hazard intensity\")\n",
" ax.set_ylabel(\"Impact Factor\")\n",
" \n",
" plt.tight_layout()\n",
" display(fig)\n",
" plt.close(fig) # Close the figure to free up memory\n",
"def preview_impact_func():\n",
" if approach_selector.value != 'Function':\n",
" return\n",
" \n",
" with approach_box:\n",
" clear_output(wait=True) # Clear the previous output\n",
" selected_exposures = exposure_selector.value\n",
" if not selected_exposures:\n",
" print(\"Please select at least one exposure category\") \n",
" return\n",
"\n",
" steps = np.arange(0, 6, 0.1)\n",
" fig, ax = plt.subplots(figsize=(4, 3))\n",
" \n",
" damage_factors = {\n",
" 'POP': mortality_factor,\n",
" 'BU': damage_factor_builtup,\n",
" 'AGR': damage_factor_agri\n",
" }\n",
" \n",
" for exposure in selected_exposures:\n",
" if exposure in damage_factors:\n",
" damage_factor = damage_factors[exposure]\n",
" _, = ax.plot([damage_factor(x) for x in steps], label=exposure)\n",
" else:\n",
" print(\"Please select at least one exposure category\")\n",
" print(f\"Unknown exposure category: {exposure}\")\n",
" \n",
" ax.grid(True)\n",
" ax.legend()\n",
" \n",
" label_steps = range(0, len(steps)+10, 10)\n",
" ax.set_xticks(label_steps)\n",
" ax.set_xticklabels([i / 10 for i in label_steps])\n",
" ax.set_xlabel(\"Hazard intensity\")\n",
" ax.set_ylabel(\"Impact Factor\")\n",
" \n",
" plt.tight_layout()\n",
" display(fig)\n",
" plt.close(fig) # Close the figure to free up memory\n",
"\n",
"# Define add_class_button before using it\n",
"add_class_button = widgets.Button(description=\"Add Class\", layout=widgets.Layout(width='150px'))\n",
Expand All @@ -322,21 +266,19 @@
"\n",
"def update_delete_buttons():\n",
" for child in class_edges_table.children[:-1]: # Exclude the \"Add Class\" button\n",
" if len(class_edges_table.children) > 2: # More than one class row plus the \"Add Class\" button\n",
" child.children[2].layout.display = 'block'\n",
" else:\n",
" child.children[2].layout.display = 'none'\n",
" display_text = 'block' if len(class_edges_table.children) > 2 else 'none'\n",
" child.children[2].layout.display = display_text\n",
"\n",
"# Define add_class_button\n",
"add_class_button = widgets.Button(description=\"Add Class\", layout=widgets.Layout(width='150px'))\n",
"add_class_button.on_click(lambda b: add_class(b))\n",
"\n",
"def add_class(button):\n",
"def add_class():\n",
" new_index = len(class_edges_table.children)\n",
" class_edges_table.children = list(class_edges_table.children[:-1]) + [create_class_row(new_index)] + [add_class_button]\n",
" update_delete_buttons()\n",
"\n",
"def update_class_edges_table(*args):\n",
"def update_class_edges_table():\n",
" approach_box.clear_output()\n",
" with approach_box:\n",
" if approach_selector.value == 'Classes':\n",
Expand Down Expand Up @@ -389,24 +331,25 @@
" 'f': 'json'\n",
" }\n",
" response = requests.get(url, params=params)\n",
" if response.status_code == 200:\n",
" data = response.json()\n",
" if not data['features']:\n",
" print(f\"Error: {iso_a3} is not a valid ISO_A3 code.\")\n",
" return False\n",
" else:\n",
" \n",
" if response.status_code != 200:\n",
" print(\"Error: Unable to validate country code. Please ensure you are connected to the internet.\")\n",
" return False\n",
"\n",
" data = response.json()\n",
" if not data['features']:\n",
" print(f\"Error: {iso_a3} is not a valid ISO_A3 code.\")\n",
" return False\n",
" \n",
" # Check class thresholds\n",
" print(\"Checking class thresholds...\")\n",
" if approach_selector.value == 'Classes':\n",
" print(\"Checking class thresholds...\")\n",
" class_values = [child.children[1].value for child in class_edges_table.children[:-1]] # Exclude \"Add Class\" button\n",
" if len(class_values) > 1:\n",
" for i in range(1, len(class_values)):\n",
" if class_values[i] <= class_values[i-1]:\n",
" print(f\"Error: Class {i+1} threshold ({class_values[i]}) must be greater than Class {i} threshold ({class_values[i-1]}).\")\n",
" return False\n",
" \n",
" is_seq = np.all(np.diff(class_values) > 0)\n",
" if not is_seq:\n",
" print(\"Error: Ensure that all class thresholds are ordered in ascending order.\")\n",
" return False\n",
"\n",
" print(\"User input accepted!\")\n",
" return True\n",
Expand All @@ -433,9 +376,7 @@
" min_haz_slider = hazard_threshold_slider.value\n",
" \n",
" # Get class thresholds if applicable\n",
" class_edges = []\n",
" if analysis_type == 'Classes':\n",
" class_edges = [child.children[1].value for child in class_edges_table.children[:-1]] # Exclude \"Add Class\" button\n",
" class_edges = [child.children[1].value for child in class_edges_table.children[:-1]] if analysis_type == 'Classes' else [] # Exclude \"Add Class\" button\n",
" \n",
" # Determine exp_nam_list\n",
" if custom_exposure_radio.value == 'Custom exposure':\n",
Expand Down
1 change: 0 additions & 1 deletion tools/code/Floods_Fathom3/common.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# This file includes common configuration elements used by the script.

import os

# Load env vars from dotenv file
Expand Down
Loading