Skip to content

Commit

Permalink
353 make sure manual vulnerability curves of damage estimation work (#…
Browse files Browse the repository at this point in the history
…442)

## Issue addressed
Solves #<issue number>

## Code of conduct
- [x] I HAVE NOT added sensitive or compromised (test) data to the
repository.
- [x] I HAVE NOT added vulnerabilities to the repository.
- [x] I HAVE discussed my solution with (other) members of the RA2CE
team.

## What has been done?
Explain how you addressed the resolution of the related issue, what
choices you made and why.

### Checklist
- [ ] Code is formatted using our custom `black` and `isort`
definitions.
- [x] Tests are either added or updated.
- [x] Branch is up to date with `master`.
- [x] Updated documentation if needed.

## Additional Notes (optional)
Add any additional notes or information that may be helpful.
  • Loading branch information
sahand-asgarpour authored May 28, 2024
2 parents 7e3b259 + b628ebd commit 39b702f
Show file tree
Hide file tree
Showing 6 changed files with 286 additions and 6 deletions.
2 changes: 1 addition & 1 deletion examples/data/direct_analysis_manual/analysis.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = beira

[analysis1]
name = Huizinga_direct_damage_event
name = Manual_direct_damage_event
analysis = direct
event_type = event
damage_curve = MAN
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
depth;damage
cm;% of total construction costs
0;0
100;0.1
200;0.2
400;0.4
800;0.8
12000;1
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Road_type \ lanes;1;2;3;4;5
unit;euro/m;euro/m;euro/m;euro/m;euro/m
tertiary_link;110;120;130;140;150
tertiary;110;120;130;140;150
secondary_link;11;12;13;14;15
secondary;11;12;13;14;15
residential;1100;1200;1300;1400;1500
['tertiary', 'residential'];510;520;530;540;550
264 changes: 264 additions & 0 deletions examples/example_direct_damage_manual.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# RA2CE feature: Direct analysis"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Three types of damage curves can be introduced to this analysis:\n",
"- Huizinga\n",
"- OSdaMage \n",
"- User defined"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## An example for a manual damage function"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"In this notebook, we provide an example for an event-based object-oriented Huizinga analysis."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import geopandas as gpd\n",
"import matplotlib.pyplot as plt\n",
"from pathlib import Path\n",
"import rasterio\n",
"from ra2ce.ra2ce_handler import Ra2ceHandler #import the ra2cehandler to run ra2ce analyses\n",
"\n",
"root_dir = Path(\"data\", \"direct_analysis_manual\")\n",
"assert root_dir.exists(), \"root_dir not found.\""
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Introducing a hazardous event"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"To use the flood map with RA2CE, we need to fill in the **[hazard]** section in the network.ini. \n",
"\n",
"Specify the flood map name in the **hazard_map** parameter in network.ini. RA2CE expects the flood map to be located in the *hazard* folder. The **aggregate_wl** parameter in analysis.ini can be set to either 'max', 'min' or 'mean' to take the maximum, minimum or mean water depth per road segment when the exposure of the roads to a certain hazard (map) is determined.<br>\n",
"\n",
"Set the right CRS for the flood map in the **hazard_crs** parameter. This CRS can be different from the origins, destinations and road network. RA2CE will reproject the network to the CRS of the flood map and will reproject the road back to the original CRS when the CRS differs."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"hazard_folder = root_dir / \"static\" / \"hazard\" # find the hazard folder where you locate your floo dmap\n",
"hazard_map = hazard_folder / \"max_flood_depth.tif\" # set the location of the hazard map\n",
"\n",
"# Open the TIF file using rasterio\n",
"with rasterio.open(hazard_map) as src:\n",
" # Read the TIF file as a numpy array\n",
" tif_array = src.read(1) # Change the band index (1) if necessary\n",
"\n",
"plt.figure(figsize=(10, 10))\n",
"plt.imshow(tif_array, cmap='Blues') # Change the colormap if desired\n",
"plt.colorbar(label='Pixel Values')\n",
"plt.title('Flood map')\n",
"plt.show()\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Specifying the .ini files"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**Network.ini content**\n",
"<br>\n",
"<br>\n",
"> [project]<br>\n",
"name = beira<br>\n",
"<br>\n",
"[network]<br>\n",
"**directed = False<br>\n",
"source = OSM download<br>\n",
"primary_file = None<br>\n",
"diversion_file = None<br>\n",
"file_id = rfid_c<br>\n",
"polygon = region_polygon.geojson<br>\n",
"network_type = drive<br>\n",
"road_types = motorway,motorway_link,primary,primary_link,secondary,secondary_link,tertiary,tertiary_link,residential<br>\n",
"save_gpkg = True\n",
"<br>\n",
"[origins_destinations]<br>\n",
"**origins = None<br>\n",
"destinations = None<br>\n",
"origins_names = None<br>\n",
"destinations_names = None<br>\n",
"id_name_origin_destination = None<br>\n",
"origin_count = None<br>\n",
"origin_out_fraction = None<br>\n",
"category = category**<br>\n",
"<br>\n",
"[hazard]<br>\n",
"**hazard_map = max_flood_depth.tif<br>\n",
"hazard_id = None<br>\n",
"hazard_field_name = waterdepth<br>\n",
"aggregate_wl = max<br>\n",
"hazard_crs = EPSG:32736**<br>\n",
"<br>\n",
"*[cleanup]<br>\n",
"snapping_threshold = None<br>\n",
"segmentation_length = None<br>\n",
"merge_lines = True<br>\n",
"merge_on_id = False<br>\n",
"cut_at_intersections = False<br>*"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"We now need to update our analysis initialisation files using the preferred OD-analysis (there are multiple). We will consider the **direct** analysis. With the **aggregate_wl** parameter, the user can choose which type of aggregation of the water level on the road segment (max, mean, min) the analysis should consider. For the direct analysis, the **aggregate_wl=mean** makes sense. \n",
"\n",
"The **damage_curve** defines the damage curve type. ‘HZ’ to use the Huizinga damage function, ‘OSD’ to use the OSdaMage functions, and ‘MAN’ to use damage functions from manually inserted files. The **event_type** defines the type of the hazardous event, which is either 'event', or 'return_period'. The former is an one-time event, while the later will be applied for the events witha probability of occurance."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"**[analysis1]**\n",
"<br>\n",
"<br>\n",
"name = Manual_direct_damage_event<br>\n",
"analysis = direct<br>\n",
"event_type = event<br>\n",
"damage_curve = MAN<br>\n",
"save_csv = True<br>\n",
"save_gpkg =True<br>"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Set the paths to the initialization files and check if the files exist."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from ra2ce.ra2ce_handler import Ra2ceHandler\n",
"from ra2ce.network.network_config_data.network_config_data_reader import NetworkConfigDataReader\n",
"from ra2ce.analysis.analysis_config_data.analysis_config_data_reader import AnalysisConfigDataReader\n",
"\n",
"# Load network data.\n",
"_network_config_data = NetworkConfigDataReader().read(root_dir.joinpath(\"network.ini\"))\n",
"\n",
"# Load analysis data.\n",
"_analysis_config_data = AnalysisConfigDataReader().read(root_dir.joinpath(\"analysis.ini\"))\n",
"\n",
"_analysis_config_data.input_path = root_dir.joinpath(\"input_data\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Run RA2CE."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"handler = Ra2ceHandler.from_config(_network_config_data, _analysis_config_data)\n",
"\n",
"handler.configure()\n",
"handler.run_analysis()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Visualising the results"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"analysis_output_path = root_dir / \"output\" / \"direct\"\n",
"damage_gdf = gpd.read_file(analysis_output_path / 'Manual_direct_damage_event.gpkg')\n",
"damage_gdf.head() #show the origins"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "ra2ce_env",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.13"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def add_max_damage(self, df: pd.DataFrame, prefix: str = None):

max_damage_data = self.max_damage.data
df["{}_temp_max_dam".format(prefix)] = max_damage_data.lookup(
df["road_type"], df["lanes"]
df["infra_type"], df["lanes"]
)
return df

Expand Down
8 changes: 4 additions & 4 deletions ra2ce/analysis/direct/damage/max_damage.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,16 @@ def __init__(self, name=None, damage_unit=None):
def from_csv(self, path: Path, sep=",") -> None:
"""Construct object from csv file. Damage curve name is inferred from filename
The first row describe the lane numbers per column; and should have 'Road_type \ lanes' as index/first value
The first row describe the lane numbers per column; and should have 'Road_type \ lanes' as index/first value.
Assume road types are in the rows; lane numbers in the columns.
The second row has the units per column, and should have 'unit' as index/first value
the rest of the rows contains the different road types as index/first value; and the costs as values
Arguments:
*path* (Path) : Path to the csv file
*sep* (str) : csv seperator
*output_unit* (str) : desired output unit (default = 'euro/m')
"""
default_output_unit = "euro/m"
self.name = path.stem
self.raw_data = pd.read_csv(path, index_col=r"Road_type \ lanes", sep=sep)
self.origin_path = path # to track the original path from which the object was constructed; maybe also date?
Expand All @@ -80,7 +80,7 @@ def from_csv(self, path: Path, sep=",") -> None:
# assumes that the columns containst the lanes
self.data.columns = self.data.columns.astype("int")

if self.damage_unit != "output_unit":
if self.damage_unit != default_output_unit:
self.convert_length_unit() # convert the unit

def convert_length_unit(self, desired_unit="euro/m"):
Expand Down

0 comments on commit 39b702f

Please sign in to comment.