{ "cells": [ { "cell_type": "markdown", "id": "6461c33a", "metadata": {}, "source": [ "# Adaptation Measures\n", "\n", "Adaptation measures are defined by parameters that alter the exposures, hazard or impact functions. Risk transfer options are also considered. Single measures are defined in the `Measure` class, which can be aggregated to a `MeasureSet`.\n", "\n", "```{attention}\n", "Adapation measures and cost-benefit evaluation are being completely revamped. Associated tutorials are under their own menu [Adaptation appraisal guides](adaptation-guides).\n", "```" ] }, { "cell_type": "markdown", "id": "4e45076c", "metadata": {}, "source": [ "## Measure class\n", "\n", "A measure is characterized by the following attributes:\n", "\n", "Related to measure's description:\n", " * name (str): name of the action\n", " * haz_type (str): related hazard type (peril), e.g. TC\n", " * color_rgb (np.array): integer array of size 3. Gives color code of this measure in RGB\n", " * cost (float): discounted cost (in same units as assets). Needs to be provided by the user. See the example provided in `climada_python/climada/data/system/entity_template.xlsx` sheets `_measures_details` and `_discounting_sheet` to see how the discounting is done.\n", "\n", "Related to a measure's impact:\n", " * hazard_set (str): file name of hazard to use\n", " * hazard_freq_cutoff (float): hazard frequency cutoff\n", " * exposure_set (str): file name of exposure to use\n", " * hazard_inten_imp (tuple): parameter a and b of hazard intensity change\n", " * mdd_impact (tuple): parameter a and b of the impact over the mean damage degree\n", " * paa_impact (tuple): parameter a and b of the impact over the percentage of affected assets\n", " * imp_fun_map (str): change of impact function id, e.g. '1to3'\n", " * exp_region_id (int): region id of the selected exposures to consider ALL the previous parameters\n", " * risk_transf_attach (float): risk transfer attachment. Applies to the whole exposure.\n", " * risk_transf_cover (float): risk transfer cover. Applies to the whole exposure.\n", "\n", "Parameters description:\n", "\n", "`hazard_set` and `exposures_set` provide the file names in h5 format (generated by CLIMADA) of the hazard and exposures to use as a result of the implementation of the measure. These might be further modified when applying the other parameters.\n", "\n", "`hazard_inten_imp`, `mdd_impact` and `paa_impact` transform the impact functions linearly as follows:\n", "\n", " intensity = intensity*hazard_inten_imp[0] + hazard_inten_imp[1]\n", " mdd = mdd*mdd_impact[0] + mdd_impact[1]\n", " paa = paa*paa_impact[0] + paa_impact[1]\n", "\n", "`hazard_freq_cutoff` modifies the hazard by putting 0 intensities to the events whose impact exceedance frequency are greater than `hazard_freq_cutoff`.\n", "\n", "`imp_fun_map` indicates the ids of the impact function to replace and its replacement. The `impf_XX` variable of `Exposures` with the affected impact function id will be correspondingly modified (`XX` refers to the `haz_type` of the measure).\n", "\n", "`exp_region_id` will apply all the previous changes only to the `region_id` indicated. This means that only the exposures with that `region_id` and the hazard's centroids close to them will be modified with the previous changes, the other regions will remain unaffected to the measure.\n", "\n", "`risk_transf_attach` and `risk_transf_cover` are the deductible and coverage of any event to happen." ] }, { "cell_type": "markdown", "id": "4f5b9bb0", "metadata": {}, "source": [ "Methods description:\n", "\n", "The method `check()` validates the attibutes. `apply()` applies the measure to a given exposure, impact function and hazard, returning their modified values. The parameters related to insurability (risk_transf_attach and risk_transf_cover) affect the resulting impact and are therefore not applied in the `apply()` method yet.\n", "\n", "`calc_impact()` calls to `apply()`, applies the insurance parameters and returns the final impact and risk transfer of the measure. This method is called from the `CostBenefit` class." ] }, { "cell_type": "markdown", "id": "123d60bf", "metadata": {}, "source": [ "The method `apply()` allows to visualize the effect of a measure. Here are some examples:" ] }, { "cell_type": "code", "execution_count": null, "id": "d2841a6d", "metadata": {}, "outputs": [], "source": [ "# effect of mdd_impact, paa_impact, hazard_inten_imp\n", "%matplotlib inline\n", "import numpy as np\n", "from climada.entity import ImpactFuncSet, ImpfTropCyclone, Exposures\n", "from climada.entity.measures import Measure\n", "from climada.hazard import Hazard\n", "\n", "# define measure\n", "meas = Measure(\n", " name=\"Mangrove\",\n", " haz_type=\"TC\",\n", " color_rgb=np.array([1, 1, 1]),\n", " cost=500000000,\n", " mdd_impact=(1, 0),\n", " paa_impact=(1, -0.15),\n", " hazard_inten_imp=(1, -10), # reduces intensity by 10\n", ")\n", "\n", "# impact functions\n", "impf_tc = ImpfTropCyclone.from_emanuel_usa()\n", "impf_all = ImpactFuncSet([impf_tc])\n", "impf_all.plot()\n", "\n", "# dummy Hazard and Exposures\n", "haz = Hazard(\"TC\") # this measure does not change hazard\n", "exp = Exposures() # this measure does not change exposures\n", "\n", "# new impact functions\n", "new_exp, new_impfs, new_haz = meas.apply(exp, impf_all, haz)\n", "axes = new_impfs.plot()\n", "axes.set_title(\"TC: Modified impact function\");" ] }, { "cell_type": "code", "execution_count": null, "id": "9b34ea69", "metadata": {}, "outputs": [], "source": [ "# effect of hazard_freq_cutoff\n", "import numpy as np\n", "from climada.entity import ImpactFuncSet, ImpfTropCyclone, Exposures\n", "from climada.entity.measures import Measure\n", "from climada.hazard import Hazard\n", "from climada.engine import ImpactCalc\n", "\n", "from climada.util import HAZ_DEMO_H5, EXP_DEMO_H5\n", "\n", "# define measure\n", "meas = Measure(\n", " name=\"Mangrove\",\n", " haz_type=\"TC\",\n", " color_rgb=np.array([1, 1, 1]),\n", " cost=500000000,\n", " hazard_freq_cutoff=0.0255,\n", ")\n", "\n", "# impact functions\n", "impf_tc = ImpfTropCyclone.from_emanuel_usa()\n", "impf_all = ImpactFuncSet([impf_tc])\n", "\n", "# Hazard\n", "haz = Hazard.from_hdf5(HAZ_DEMO_H5)\n", "haz.check()\n", "\n", "# Exposures\n", "exp = Exposures.from_hdf5(EXP_DEMO_H5)\n", "exp.check()\n", "\n", "# new hazard\n", "new_exp, new_impfs, new_haz = meas.apply(exp, impf_all, haz)\n", "# if you look at the maximum intensity per centroid: new_haz does not contain the event with smaller impact (the most frequent)\n", "haz.plot_intensity(0)\n", "new_haz.plot_intensity(0)\n", "# you might also compute the exceedance frequency curve of both hazard\n", "imp = ImpactCalc(exp, impf_all, haz).impact()\n", "ax = imp.calc_freq_curve().plot(label=\"original\")\n", "\n", "new_imp = ImpactCalc(new_exp, new_impfs, new_haz).impact()\n", "new_imp.calc_freq_curve().plot(\n", " axis=ax, label=\"measure\"\n", "); # the damages for events with return periods > 1/0.0255 ~ 40 are 0" ] }, { "cell_type": "code", "execution_count": null, "id": "03888cca", "metadata": {}, "outputs": [], "source": [ "# effect of exp_region_id\n", "import numpy as np\n", "from climada.entity import ImpactFuncSet, ImpfTropCyclone, Exposures\n", "from climada.entity.measures import Measure\n", "from climada.hazard import Hazard\n", "from climada.engine import ImpactCalc\n", "\n", "from climada.util import HAZ_DEMO_H5, EXP_DEMO_H5\n", "\n", "# define measure\n", "meas = Measure(\n", " name=\"Building code\",\n", " haz_type=\"TC\",\n", " color_rgb=np.array([1, 1, 1]),\n", " cost=500000000,\n", " hazard_freq_cutoff=0.00455,\n", " exp_region_id=[1], # apply measure to points close to exposures with region_id=1\n", ")\n", "\n", "# impact functions\n", "impf_tc = ImpfTropCyclone.from_emanuel_usa()\n", "impf_all = ImpactFuncSet([impf_tc])\n", "\n", "# Hazard\n", "haz = Hazard.from_hdf5(HAZ_DEMO_H5)\n", "haz.check()\n", "\n", "# Exposures\n", "exp = Exposures.from_hdf5(EXP_DEMO_H5)\n", "# exp['region_id'] = np.ones(exp.shape[0])\n", "exp.check()\n", "# all exposures have region_id=1\n", "exp.plot_hexbin(buffer=1.0)\n", "\n", "# new hazard\n", "new_exp, new_impfs, new_haz = meas.apply(exp, impf_all, haz)\n", "# the cutoff has been apllied only in the region of the exposures\n", "haz.plot_intensity(0)\n", "new_haz.plot_intensity(0)\n", "\n", "# the exceddance frequency has only been computed for the selected exposures before doing the cutoff.\n", "# since we have removed the hazard of the places with exposure, the new exceedance frequency curve is zero.\n", "imp = ImpactCalc(exp, impf_all, haz).impact()\n", "imp.calc_freq_curve().plot()\n", "\n", "new_imp = ImpactCalc(new_exp, new_impfs, new_haz).impact()\n", "new_imp.calc_freq_curve().plot();" ] }, { "cell_type": "code", "execution_count": null, "id": "a1454057", "metadata": {}, "outputs": [], "source": [ "# effect of risk_transf_attach and risk_transf_cover\n", "import numpy as np\n", "from climada.entity import ImpactFuncSet, ImpfTropCyclone, Exposures\n", "from climada.entity.measures import Measure\n", "from climada.hazard import Hazard\n", "from climada.engine import ImpactCalc\n", "\n", "from climada.util import HAZ_DEMO_H5, EXP_DEMO_H5\n", "\n", "# define measure\n", "meas = Measure(\n", " name=\"Insurance\",\n", " haz_type=\"TC\",\n", " color_rgb=np.array([1, 1, 1]),\n", " cost=500000000,\n", " risk_transf_attach=5.0e8,\n", " risk_transf_cover=1.0e9,\n", ")\n", "\n", "# impact functions\n", "impf_tc = ImpfTropCyclone.from_emanuel_usa()\n", "impf_all = ImpactFuncSet([impf_tc])\n", "\n", "# Hazard\n", "haz = Hazard.from_hdf5(HAZ_DEMO_H5)\n", "haz.check()\n", "\n", "# Exposures\n", "exp = Exposures.from_hdf5(EXP_DEMO_H5)\n", "exp.check()\n", "\n", "# impact before\n", "imp = ImpactCalc(exp, impf_all, haz).impact()\n", "ax = imp.calc_freq_curve().plot(label=\"original\")\n", "\n", "# impact after. risk_transf will be added to the cost of the measure\n", "imp_new, risk_transf = meas.calc_impact(exp, impf_all, haz)\n", "imp_new.calc_freq_curve().plot(axis=ax, label=\"measure\")\n", "print(\"risk_transfer {:.3}\".format(risk_transf.aai_agg))" ] }, { "cell_type": "markdown", "id": "b89c65c0", "metadata": {}, "source": [ "## MeasureSet class\n", "\n", "Similarly to the `ImpactFuncSet`, `MeasureSet` is a container which handles `Measure` instances through the methods `append()`, `extend()`, `remove_measure()`and `get_measure()`. Use the `check()` method to make sure all the measures have been properly set.\n", "\n", "For a complete class documentation, refer to the Python modules docs: {py:class}`climada.entity.measures.measure_set.MeasureSet`" ] }, { "cell_type": "code", "execution_count": null, "id": "a47f76d9", "metadata": {}, "outputs": [], "source": [ "# build measures\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from climada.entity.measures import Measure, MeasureSet\n", "\n", "meas_1 = Measure(\n", " haz_type=\"TC\",\n", " name=\"Mangrove\",\n", " color_rgb=np.array([1, 1, 1]),\n", " cost=500000000,\n", " mdd_impact=(1, 2),\n", " paa_impact=(1, 2),\n", " hazard_inten_imp=(1, 2),\n", " risk_transf_cover=500,\n", ")\n", "\n", "meas_2 = Measure(\n", " haz_type=\"TC\",\n", " name=\"Sandbags\",\n", " color_rgb=np.array([1, 1, 1]),\n", " cost=22000000,\n", " mdd_impact=(1, 2),\n", " paa_impact=(1, 3),\n", " hazard_inten_imp=(1, 2),\n", " exp_region_id=2,\n", ")\n", "\n", "# gather all measures\n", "meas_set = MeasureSet()\n", "meas_set.append(meas_1)\n", "meas_set.append(meas_2)\n", "meas_set.check()\n", "\n", "# select one measure\n", "meas_sel = meas_set.get_measure(name=\"Sandbags\")\n", "print(meas_sel[0].name, meas_sel[0].cost)" ] }, { "cell_type": "markdown", "id": "a4f5557a", "metadata": {}, "source": [ "## Read/write measure sets to/from Excel files\n", "\n", "Measures defined in an excel file following the template provided in sheet `measures` of `climada_python/data/system/entity_template.xlsx` can be ingested directly using the method `from_excel()`. Measure sets can be written to file with the method `write_excel()`." ] }, { "cell_type": "code", "execution_count": null, "id": "e7e36c1c", "metadata": {}, "outputs": [], "source": [ "from climada.entity.measures import MeasureSet\n", "from climada.util import ENT_TEMPLATE_XLS\n", "\n", "# Fill DataFrame from Excel file\n", "file_name = ENT_TEMPLATE_XLS # provide absolute path of the excel file\n", "meas_set = MeasureSet.from_excel(file_name)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 5 }