{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Vulnerability configuration\n", "As discussed in the Introduction, a significant portion of vulnerability models can be represented by a generic vulnerability model and the specification of a model configuration. In particular, damage curves are often used to relate a hazard indicator value (e.g. flood depth) to damage to an asset, to contents/inventory or asset downtime.\n", "\n", "## Types of curve\n", "The configuration comprises two types of vulnerability curve:\n", "1) *Damage curves* \n", "For acute risks, this specifies the fractional damage or disruption (e.g. downtime or loss of production), given the occurrence of a hazard with a given indicator value.\n", "`curve_type`: `indicator/piecewise_linear`. \n", "e.g. for riverine flood, the curve $x$ values are depth in metres and the curve $y$ values are damage as fraction of total insurable value.\n", "\n", "2) *Threshold curves* \n", "For chronic risks, this specifies the fractional damage or disruption that occurs for hazard indicator threshold values. This is for hazard indicators that give the mean amount of time per year for which an indicator is greater than a threshold value. \n", "`curve_type`: `threshold/piecewise_linear`. \n", "e.g. for chronic heat, the indicator might be the number of days per year for which the maximum near-surface air temperature is greater than $t$ degrees, $t$ being the threshold values. The curve $x$ values are the thresholds in degrees Celsius and the curve $y$ values are the losses in production that occur for each day for which the maximum temperature is at that value.\n", "\n", "## Identifying assets\n", "Assets are identified by:\n", "- Asset class. This is the *broad* class of asset e.g. real estate assets or power generating assets within which asset vulnerabilities tend to be modelled in a similar way and which tend to have a common set of attributes. The set of valid asset classes is defined within physrisk itself.\n", "- A number of asset attributes.\n", "Specifying the asset class is optional in that vulnerability curves can be defined for the parent `Asset` type, in which case only asset attributes are relevant.\n", "\n", "### Identifying assets within the configuration \n", "The vulnerability function is associated to an asset by specification of the asset class and by a set of attribute key/value pairs in the form of a comma-separated string: '==,...'. The attributes are matched to those of the asset.\n", "\n", "### Example 1: simple type/location model\n", "We define two special attribute names: `type` and `location`. These are particularly suited for *sectorial* modelling applications or similar where little is known about the asset other than its class, some information about the type within the class and its location. For example, configuration might be provided for real estate assets in the form 'type=Buildings/Commercial,location=Europe'. For sectorial analyses, `type` is based around industry classifications (e.g. NACE codes). \n", "\n", "### Example 2: occupancy identifier and attributes\n", "*Occupancy* classifications are used to group assets with similar characteristics related to valuation and damage, or disruption characteristics. \n", "There are a number of important occupancy schemes, for example Open Exposure Data (OED). Assets can be identified via, `occupancy_scheme`, `occupancy_id` and a set of attributes needed to refine the selection, e.g. number of storeys within a particular occupancy identifier.\n", "\n", "### Example 3: explicit specification of curve\n", "For families of vulnerability functions, we can define a set of curves by, e.g. 'hazus_flood_curve_id=43'.\n", "\n", "In all cases, logic in the code maps an asset's attributes onto the attributes that define the vulnerability function.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Damage/disruption function specification\n", "\n", "The scheme is designed to allow uncertainly in damage/disruption functions to be specified as well as the deterministic case comprising hazard indicator ($x$) values and the corresponding impact (damage/disruption) ($y$) values. This can be captured by $x$ and $y$ fields each containing an array. A third $z$ field to capture information about the uncertainty in the vulnerability functions.\n", "\n", "#### Case 1: deterministic damage curve provided\n", "The hazard indicator values, $x_i$, are given, $i \\in [1 \\dots n]$ and the corresponding impacts $y_i$.\n", "\n", "$x = [x_1, x_2, \\dots, x_n]$ \n", "$y = [y_1, y_2, \\dots, y_n]$ \n", "$z$ is empty\n", "\n", "#### Case 2: mean and standard deviation provided\n", "The hazard indicator values, $x_i$, are given, $i \\in [1 \\dots n]$.\n", "\n", "$f_i(y) = \\mathbb{P}(Y=y|x_i)$ \n", "$\\mu_i = \\int f_i(y) y dy$ \n", "$\\sigma_i^2 = \\int f_i(y) y^2 dy - \\mu_i^2$\n", "\n", "The means are given in $y$ and the standard deviations in $z$.\n", "\n", "$x = [x_1, x_2, \\dots, x_n ]$ \n", "$y = [\\mu_1, \\mu_2, \\dots, \\mu_n ]$ \n", "$z = [\\sigma_1, \\sigma_2, \\dots, \\sigma_n ]$\n", "\n", "#### Case 3: discrete piece-wise linear cumulative density function (CDF) provided\n", "The hazard indicator values, $x_i$, are given, $i \\in [1 \\dots n]$.\n", "\n", "$F_i(y) = \\mathbb{P}(Y \\leq y|x_i)$\n", "\n", "The CDF, $F_i(y)$, is given for points $y_j$, $j \\in [1 \\dots m]$.\n", "$F_{ij} = \\mathbb{P}(Y \\leq y_j|x_i)$\n", "\n", "$x = [x_1, x_2, \\dots, x_n ]$ \n", "$y = [y_1, y_2, \\dots, y_m ]$ \n", "$z = [[F_{11}, F_{12}, \\dots, F_{1m}], [F_{21}, F_{12}, \\dots, F_{2m}], \\dots, [F_{n1}, F_{n2}, \\dots, F_{nm}]]$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Example configuration: displaying" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# pip install nbformat pandas plotly requests\n", "from dotenv import load_dotenv\n", "from io import StringIO\n", "import plotly.graph_objs as go\n", "import plotly.io\n", "from plotly.subplots import make_subplots\n", "\n", "plotly.io.renderers.default = \"notebook\"\n", "from physrisk.vulnerability_models.config_based_impact_curves import config_items_from_csv, config_items_to_df" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Rainbow CSV is a useful add-in for dealing with vulnerability config as CSV.\n", "# Here we paste in a couple of lines.\n", "\n", "config_lines = \"\"\"\n", "hazard_class,asset_class,asset_identifier,indicator_id,indicator_units,impact_id,impact_units,curve_type,points_x,points_y,cap_of_points_x,cap_of_points_y,activation_of_points_x\n", "\"CoastalInundation,PluvialInundation,RiverineInundation,\",RealEstateAsset,\"type=Buildings/Residential,location=Europe\",flood_depth,metres,damage,,indicator/piecewise_linear,\"[0.05, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0]\",\"[0.0, 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1.0]\",,,\n", "ChronicHeat,ManufacturingAsset,\"type=Chemical,location=Generic\",days_tas/above/{temp_c}c,days/year,disruption,,threshold/piecewise_linear,\"[15.0, 25.0, 35.0, 45.0, 55.0, 65.0]\",\"[0.0, 0.1, 0.25, 0.5, 0.8, 1.0]\",,,\n", "\"\"\"" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hazard_classasset_classasset_identifierindicator_idindicator_unitsimpact_idimpact_unitscurve_typepoints_xpoints_ypoints_zcap_of_points_xcap_of_points_yactivation_of_points_x
0ChronicHeatManufacturingAssettype=Chemical,location=Genericdays_tas/above/{temp_c}cdays/yeardisruptionNonethreshold/piecewise_linear[15.0, 25.0, 35.0, 45.0, 55.0, 65.0][0.0, 0.1, 0.25, 0.5, 0.8, 1.0]NoneNoneNoneNone
1CoastalInundationRealEstateAssettype=Buildings/Residential,location=Europeflood_depthmetresdamageNoneindicator/piecewise_linear[0.05, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0][0.0, 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1.0]NoneNoneNoneNone
2PluvialInundationRealEstateAssettype=Buildings/Residential,location=Europeflood_depthmetresdamageNoneindicator/piecewise_linear[0.05, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0][0.0, 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1.0]NoneNoneNoneNone
3RiverineInundationRealEstateAssettype=Buildings/Residential,location=Europeflood_depthmetresdamageNoneindicator/piecewise_linear[0.05, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0][0.0, 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1.0]NoneNoneNoneNone
\n", "
" ], "text/plain": [ " hazard_class asset_class \\\n", "0 ChronicHeat ManufacturingAsset \n", "1 CoastalInundation RealEstateAsset \n", "2 PluvialInundation RealEstateAsset \n", "3 RiverineInundation RealEstateAsset \n", "\n", " asset_identifier indicator_id \\\n", "0 type=Chemical,location=Generic days_tas/above/{temp_c}c \n", "1 type=Buildings/Residential,location=Europe flood_depth \n", "2 type=Buildings/Residential,location=Europe flood_depth \n", "3 type=Buildings/Residential,location=Europe flood_depth \n", "\n", " indicator_units impact_id impact_units curve_type \\\n", "0 days/year disruption None threshold/piecewise_linear \n", "1 metres damage None indicator/piecewise_linear \n", "2 metres damage None indicator/piecewise_linear \n", "3 metres damage None indicator/piecewise_linear \n", "\n", " points_x \\\n", "0 [15.0, 25.0, 35.0, 45.0, 55.0, 65.0] \n", "1 [0.05, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0] \n", "2 [0.05, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0] \n", "3 [0.05, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0] \n", "\n", " points_y points_z cap_of_points_x \\\n", "0 [0.0, 0.1, 0.25, 0.5, 0.8, 1.0] None None \n", "1 [0.0, 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1.0] None None \n", "2 [0.0, 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1.0] None None \n", "3 [0.0, 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1.0] None None \n", "\n", " cap_of_points_y activation_of_points_x \n", "0 None None \n", "1 None None \n", "2 None None \n", "3 None None " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "config_items = config_items_from_csv(StringIO(config_lines))\n", "df = config_items_to_df(config_items)\n", "display(df)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c1 = next(c for c in config_items if c.asset_class == \"RealEstateAsset\" and c.indicator_id==\"flood_depth\")\n", "c2 = next(c for c in config_items if c.asset_class == \"ManufacturingAsset\" and c.indicator_id==\"days_tas/above/{temp_c}c\")\n", "\n", "fig1 = make_subplots(rows=1, cols=2)\n", "fig1.add_scatter(x=c1.points_x, y=c1.points_y, name=\"Example damage curve\", row=1, col=1)\n", "fig1.add_scatter(x=c2.points_x, y=c2.points_y, name=\"Example threshold curve\", row=1, col=2)\n", "fig1.update_xaxes(title=\"Flood depth (m)\", title_font={\"size\": 14}, row=1, col=1)\n", "fig1.update_xaxes(title=\"Threshold (°C)\", title_font={\"size\": 14}, row=1, col=2)\n", "fig1.update_yaxes(title=\"Damage as fraction of insurable value\", row=1, col=1)\n", "fig1.update_yaxes(title=\"Fractional loss of production\", row=1, col=2)\n", "fig1.update_layout(legend=dict(orientation=\"h\", y=-0.15))\n", "#fig1.update_layout(legend=dict(yanchor=\"top\", y=0.99, xanchor=\"left\", x=0.01))\n", "fig1.update_layout(margin=dict(l=20, r=20, t=20, b=20))" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "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.15" } }, "nbformat": 4, "nbformat_minor": 2 }