def test_calc_imp_mat_pass(self): """Test save imp_mat""" # Read default entity values ent = Entity() ent.read_excel(ENT_DEMO_TODAY) ent.check() # Read default hazard file hazard = Hazard('TC') hazard.read_mat(HAZ_TEST_MAT) # Create impact object impact = Impact() # Assign centroids to exposures ent.exposures.assign_centroids(hazard) # Compute the impact over the whole exposures impact.calc(ent.exposures, ent.impact_funcs, hazard, save_mat=True) self.assertTrue(isinstance(impact.imp_mat, sparse.csr_matrix)) self.assertEqual(impact.imp_mat.shape, (hazard.event_id.size, ent.exposures.value.size)) self.assertTrue( np.allclose( np.sum(impact.imp_mat, axis=1).reshape(-1), impact.at_event)) self.assertTrue( np.allclose( np.array( np.sum(np.multiply(impact.imp_mat.toarray(), impact.frequency.reshape(-1, 1)), axis=0)).reshape(-1), impact.eai_exp))
def test_impact_year_set_empty(self): """Test result for empty impact""" imp = Impact() iys_all = imp.calc_impact_year_set() iys = imp.calc_impact_year_set(all_years=False) self.assertEqual(len(iys), 0) self.assertEqual(len(iys_all), 0)
def test_calc_imp_mat_pass(self): """Test save imp_mat""" # Read default entity values ent = Entity() ent.read_excel(ENT_DEMO_TODAY) ent.check() # Read default hazard file hazard = Hazard('TC') hazard.read_mat(HAZ_TEST_MAT) # Create impact object impact = Impact() # Assign centroids to exposures ent.exposures.assign_centroids(hazard) # Compute the impact over the whole exposures impact.calc(ent.exposures, ent.impact_funcs, hazard, save_mat=True) self.assertIsInstance(impact.imp_mat, sparse.csr_matrix) self.assertEqual(impact.imp_mat.shape, (hazard.event_id.size, ent.exposures.gdf.value.size)) np.testing.assert_array_almost_equal_nulp( np.array(impact.imp_mat.sum(axis=1)).ravel(), impact.at_event, nulp=5) np.testing.assert_array_almost_equal_nulp( np.sum(impact.imp_mat.toarray() * impact.frequency[:, None], axis=0).reshape(-1), impact.eai_exp)
def test_write_read_excel_pass(self): """Test write and read in excel""" ent = Entity() ent.read_excel(ENT_DEMO_TODAY) ent.check() hazard = Hazard('TC') hazard.read_mat(HAZ_TEST_MAT) imp_write = Impact() ent.exposures.assign_centroids(hazard) imp_write.calc(ent.exposures, ent.impact_funcs, hazard) file_name = os.path.join(DATA_FOLDER, 'test.xlsx') imp_write.write_excel(file_name) imp_read = Impact() imp_read.read_excel(file_name) self.assertTrue(np.array_equal(imp_write.event_id, imp_read.event_id)) self.assertTrue(np.array_equal(imp_write.date, imp_read.date)) self.assertTrue(np.array_equal(imp_write.coord_exp, imp_read.coord_exp)) self.assertTrue(np.allclose(imp_write.eai_exp, imp_read.eai_exp)) self.assertTrue(np.allclose(imp_write.at_event, imp_read.at_event)) self.assertTrue(np.array_equal(imp_write.frequency, imp_read.frequency)) self.assertEqual(imp_write.tot_value, imp_read.tot_value) self.assertEqual(imp_write.aai_agg, imp_read.aai_agg) self.assertEqual(imp_write.unit, imp_read.unit) self.assertEqual( 0, len([ i for i, j in zip(imp_write.event_name, imp_read.event_name) if i != j ])) self.assertIsInstance(imp_read.crs, dict)
def test_impact_pnt_agg(self): """Test impact agreggation method""" gdf_mix = GDF_LINE.append(GDF_POLY).append(GDF_POINT).reset_index( drop=True) exp_mix = Exposures(gdf_mix) exp_pnt = u_lp.exp_geom_to_pnt(exp_mix, res=1, to_meters=False, disagg_met=u_lp.DisaggMethod.DIV, disagg_val=None) imp_pnt = Impact() imp_pnt.calc(exp_pnt, IMPF_SET, HAZ, save_mat=True) imp_agg = u_lp.impact_pnt_agg(imp_pnt, exp_pnt.gdf, u_lp.AggMethod.SUM) aai_agg = 1282901.377219451 eai_exp = np.array([ 1.73069928e-04, 8.80741357e-04, 4.32240819e-03, 8.62816073e-03, 2.21441154e-02, 1.09329988e-02, 8.58546479e-02, 4.62370081e-02, 8.99584440e-02, 1.27160538e-02, 8.60317575e-02, 2.02440009e-01, 2.32808488e-02, 2.86159458e-02, 4.26205598e-03, 2.40051484e-01, 5.29133033e-03, 2.72705887e-03, 8.87954091e-03, 2.95633263e-02, 6.33106879e-01, 1.33011693e-03, 1.11120718e-01, 7.72573773e-02, 6.12233710e-03, 1.61239410e-02, 1.01492204e-01, 7.45522678e-02, 1.41155415e-01, 1.53820450e-01, 2.27951125e-02, 2.23629697e-02, 8.59651753e-03, 5.98415680e-03, 1.24717770e-02, 1.24717770e-02, 1.48060577e-05, 1.48060577e-05, 5.18270742e-03, 5.18270742e-03, 8.36178802e+03, 7.30704698e+03, 1.20628926e+04, 3.54061498e+04, 1.23524320e+04, 7.78074661e+04, 1.28292995e+05, 2.31231953e+05, 1.31911226e+05, 5.37897306e+05, 8.37016948e+04, 1.65661030e+04 ]) check_impact(self, imp_agg, HAZ, exp_mix, aai_agg, eai_exp)
def _cutoff_hazard_damage(self, exposures, if_set, hazard): """Cutoff of hazard events which generate damage with a frequency higher than hazard_freq_cutoff. Parameters: exposures (Exposures): exposures instance imp_set (ImpactFuncSet): impact functions instance hazard (Hazard): hazard instance Returns: ImpactFuncSet """ if self.hazard_freq_cutoff == 0: return hazard LOGGER.debug('Cutting events whose damage have a frequency > %s.', self.hazard_freq_cutoff) from climada.engine.impact import Impact imp = Impact() exp_imp = exposures if self.exp_region_id != 0: # compute impact only in selected region exp_imp = exposures[exposures.region_id == self.exp_region_id] exp_imp = Exposures(exp_imp) imp.calc(exp_imp, if_set, hazard) new_haz = copy.deepcopy(hazard) sort_idxs = np.argsort(imp.at_event)[::-1] exceed_freq = np.cumsum(imp.frequency[sort_idxs]) cutoff = exceed_freq > self.hazard_freq_cutoff sel_haz = sort_idxs[cutoff] new_haz_inten = new_haz.intensity.tolil() new_haz_inten[sel_haz, :] = np.zeros((sel_haz.size, new_haz.intensity.shape[1])) new_haz.intensity = new_haz_inten.tocsr() return new_haz
def test_calc_geom_impact_points(self): """ test calc_geom_impact() with points""" imp1 = u_lp.calc_geom_impact(EXP_POINT, IMPF_SET, HAZ, res=0.05, to_meters=False, disagg_met=u_lp.DisaggMethod.DIV, disagg_val=None, agg_met=u_lp.AggMethod.SUM) aai_agg1 = 0.0470814 imp11 = Impact() exp = EXP_POINT.copy() exp.set_lat_lon() imp11.calc(exp, IMPF_SET, HAZ) check_impact(self, imp1, HAZ, EXP_POINT, aai_agg1, imp11.eai_exp) imp2 = u_lp.calc_geom_impact(EXP_POINT, IMPF_SET, HAZ, res=500, to_meters=True, disagg_met=u_lp.DisaggMethod.FIX, disagg_val=1.0, agg_met=u_lp.AggMethod.SUM) exp.gdf['value'] = 1.0 imp22 = Impact() imp22.calc(exp, IMPF_SET, HAZ) aai_agg2 = 6.5454249333e-06 check_impact(self, imp2, HAZ, EXP_POINT, aai_agg2, imp22.eai_exp)
def _calc_impact(self, new_exp, new_ifs, new_haz): """Compute impact and risk transfer of measure implemented over inputs. Parameters: new_exp (Exposures): exposures once measure applied new_ifs (ImpactFuncSet): impact functions once measure applied new_haz (Hazard): hazard once measure applied Returns: Impact, Impact """ from climada.engine.impact import Impact imp = Impact() imp.calc(new_exp, new_ifs, new_haz) return imp.calc_risk_transfer(self.risk_transf_attach, self.risk_transf_cover)
def test_ref_value_pass(self): """Test result against reference value""" # Read default entity values ent = Entity() ent.read_excel(ENT_DEMO_TODAY) ent.check() # Read default hazard file hazard = Hazard('TC') hazard.read_mat(HAZ_TEST_MAT) # Create impact object impact = Impact() # Assign centroids to exposures ent.exposures.assign_centroids(hazard) # Compute the impact over the whole exposures impact.calc(ent.exposures, ent.impact_funcs, hazard) # Check result num_events = len(hazard.event_id) num_exp = ent.exposures.shape[0] # Check relative errors as well when absolute value gt 1.0e-7 # impact.at_event == EDS.damage in MATLAB self.assertEqual(num_events, len(impact.at_event)) self.assertEqual(0, impact.at_event[0]) self.assertEqual(0, impact.at_event[int(num_events / 2)]) self.assertAlmostEqual(1.472482938320243e+08, impact.at_event[13809]) self.assertEqual(7.076504723057620e+10, impact.at_event[12147]) self.assertEqual(0, impact.at_event[num_events - 1]) # impact.eai_exp == EDS.ED_at_centroid in MATLAB self.assertEqual(num_exp, len(impact.eai_exp)) self.assertAlmostEqual(1.518553670803242e+08, impact.eai_exp[0]) self.assertAlmostEqual(1.373490457046383e+08, impact.eai_exp[int(num_exp / 2)], 6) self.assertTrue( np.isclose(1.373490457046383e+08, impact.eai_exp[int(num_exp / 2)])) self.assertAlmostEqual(1.066837260150042e+08, impact.eai_exp[num_exp - 1], 6) self.assertTrue( np.isclose(1.066837260150042e+08, impact.eai_exp[int(num_exp - 1)])) # impact.tot_value == EDS.Value in MATLAB # impact.aai_agg == EDS.ED in MATLAB self.assertAlmostEqual(6.570532945599105e+11, impact.tot_value) self.assertAlmostEqual(6.512201157564421e+09, impact.aai_agg, 5) self.assertTrue(np.isclose(6.512201157564421e+09, impact.aai_agg))
def _cutoff_hazard_damage(self, exposures, impf_set, hazard): """Cutoff of hazard events which generate damage with a frequency higher than hazard_freq_cutoff. Parameters ---------- exposures : climada.entity.Exposures exposures instance imp_set : climada.entity.ImpactFuncSet impact function set instance hazard : climada.hazard.Hazard hazard instance Returns ------- new_haz : climada.hazard.Hazard Hazard without events which generate damage with a frequency higher than hazard_freq_cutoff """ if self.hazard_freq_cutoff == 0: return hazard if self.exp_region_id: # compute impact only in selected region in_reg = np.logical_or.reduce([ exposures.gdf.region_id.values == reg for reg in self.exp_region_id ]) exp_imp = Exposures(exposures.gdf[in_reg], crs=exposures.crs) else: exp_imp = exposures from climada.engine.impact import Impact imp = Impact() imp.calc(exp_imp, impf_set, hazard) LOGGER.debug('Cutting events whose damage have a frequency > %s.', self.hazard_freq_cutoff) new_haz = copy.deepcopy(hazard) sort_idxs = np.argsort(imp.at_event)[::-1] exceed_freq = np.cumsum(imp.frequency[sort_idxs]) cutoff = exceed_freq > self.hazard_freq_cutoff sel_haz = sort_idxs[cutoff] for row in sel_haz: new_haz.intensity.data[new_haz.intensity.indptr[row]:new_haz. intensity.indptr[row + 1]] = 0 new_haz.intensity.eliminate_zeros() return new_haz
def test_impact_pass(self): """Plot impact exceedence frequency curves.""" myent = Entity.from_excel(ENT_DEMO_TODAY) myent.exposures.check() myhaz = Hazard.from_mat(HAZ_DEMO_MAT) myimp = Impact() myimp.calc(myent.exposures, myent.impact_funcs, myhaz) ifc = myimp.calc_freq_curve() myax = ifc.plot() self.assertIn('Exceedance frequency curve', myax.get_title()) ifc2 = ImpactFreqCurve() ifc2.return_per = ifc.return_per ifc2.impact = 1.5e11 * np.ones(ifc2.return_per.size) ifc2.unit = '' ifc2.label = 'prove' ifc2.plot(axis=myax)
def test_excel_io(self): """Test write and read in excel""" ent = Entity.from_excel(ENT_DEMO_TODAY) ent.check() hazard = Hazard.from_mat(HAZ_TEST_MAT) imp_write = Impact() ent.exposures.assign_centroids(hazard) imp_write.calc(ent.exposures, ent.impact_funcs, hazard) file_name = DATA_FOLDER.joinpath('test.xlsx') imp_write.write_excel(file_name) imp_read = Impact.from_excel(file_name) np.testing.assert_array_equal(imp_write.event_id, imp_read.event_id) np.testing.assert_array_equal(imp_write.date, imp_read.date) np.testing.assert_array_equal(imp_write.coord_exp, imp_read.coord_exp) np.testing.assert_array_almost_equal_nulp(imp_write.eai_exp, imp_read.eai_exp, nulp=5) np.testing.assert_array_almost_equal_nulp(imp_write.at_event, imp_read.at_event, nulp=5) np.testing.assert_array_equal(imp_write.frequency, imp_read.frequency) self.assertEqual(imp_write.tot_value, imp_read.tot_value) self.assertEqual(imp_write.aai_agg, imp_read.aai_agg) self.assertEqual(imp_write.unit, imp_read.unit) self.assertEqual( 0, len([ i for i, j in zip(imp_write.event_name, imp_read.event_name) if i != j ])) self.assertIsInstance(imp_read.crs, str)
def _calc_impact(self, new_exp, new_ifs, new_haz): """Compute impact and risk transfer of measure implemented over inputs. Parameters: new_exp (Exposures): exposures once measure applied new_ifs (ImpactFuncSet): impact functions once measure applied new_haz (Hazard): hazard once measure applied Returns: Impact, float """ from climada.engine.impact import Impact imp = Impact() imp.calc(new_exp, new_ifs, new_haz) risk_transfer = 0 if self.risk_transf_attach + self.risk_transf_cover > 0: imp_layer = np.minimum(np.maximum(imp.at_event - self.risk_transf_attach, 0), self.risk_transf_cover) risk_transfer = np.sum(imp_layer * imp.frequency) imp.at_event = np.maximum(imp.at_event -imp_layer, 0) imp.aai_agg = np.sum(imp.at_event * imp.frequency) # expected annual impact per exposure no longer valid imp.eai_exp = np.array([]) return imp, risk_transfer
def test_select_event_identity_pass(self): """ test select same impact with event name, id and date """ # Read default entity values ent = Entity() ent.read_excel(ENT_DEMO_TODAY) ent.check() # Read default hazard file hazard = Hazard('TC') hazard.read_mat(HAZ_TEST_MAT) # Create impact object imp = Impact() # Assign centroids to exposures ent.exposures.assign_centroids(hazard) # Compute the impact over the whole exposures imp.calc(ent.exposures, ent.impact_funcs, hazard, save_mat=True) sel_imp = imp.select(event_ids=imp.event_id, event_names=imp.event_name, dates=(min(imp.date), max(imp.date))) self.assertEqual(sel_imp.crs, imp.crs) self.assertEqual(sel_imp.unit, imp.unit) self.assertTrue(np.array_equal(sel_imp.event_id, imp.event_id)) self.assertEqual(sel_imp.event_name, imp.event_name) self.assertTrue(np.array_equal(sel_imp.date, imp.date)) self.assertTrue(np.array_equal(sel_imp.frequency, imp.frequency)) self.assertTrue(np.array_equal(sel_imp.at_event, imp.at_event)) self.assertTrue( np.array_equal(sel_imp.imp_mat.todense(), imp.imp_mat.todense())) self.assertTrue(np.array_equal(sel_imp.eai_exp, imp.eai_exp)) self.assertAlmostEqual(round(sel_imp.aai_agg, 5), round(imp.aai_agg, 5)) self.assertEqual(sel_imp.tot_value, imp.tot_value) self.assertTrue(np.array_equal(sel_imp.coord_exp, imp.coord_exp)) self.assertIsInstance(sel_imp, Impact) self.assertIsInstance(sel_imp.imp_mat, sparse.csr_matrix)
def test_calc_if_pass(self): """Execute when no if_HAZ present, but only if_""" ent = Entity() ent.read_excel(ENT_DEMO_TODAY) ent.exposures.gdf.rename(columns={'if_TC': 'if_'}, inplace=True) ent.check() # Read default hazard file hazard = Hazard('TC') hazard.read_mat(HAZ_TEST_MAT) # Create impact object impact = Impact() impact.calc(ent.exposures, ent.impact_funcs, hazard) # Check result num_events = len(hazard.event_id) num_exp = ent.exposures.gdf.shape[0] # Check relative errors as well when absolute value gt 1.0e-7 # impact.at_event == EDS.damage in MATLAB self.assertEqual(num_events, len(impact.at_event)) self.assertEqual(0, impact.at_event[0]) self.assertEqual(0, impact.at_event[int(num_events / 2)]) self.assertAlmostEqual(1.472482938320243e+08, impact.at_event[13809]) self.assertEqual(7.076504723057620e+10, impact.at_event[12147]) self.assertEqual(0, impact.at_event[num_events - 1]) # impact.eai_exp == EDS.ED_at_centroid in MATLAB self.assertEqual(num_exp, len(impact.eai_exp)) self.assertAlmostEqual(1.518553670803242e+08, impact.eai_exp[0]) self.assertAlmostEqual(1.373490457046383e+08, impact.eai_exp[int(num_exp / 2)], 6) self.assertTrue( np.isclose(1.373490457046383e+08, impact.eai_exp[int(num_exp / 2)])) self.assertAlmostEqual(1.066837260150042e+08, impact.eai_exp[num_exp - 1], 6) self.assertTrue( np.isclose(1.066837260150042e+08, impact.eai_exp[int(num_exp - 1)])) # impact.tot_value == EDS.Value in MATLAB # impact.aai_agg == EDS.ED in MATLAB self.assertAlmostEqual(6.570532945599105e+11, impact.tot_value) self.assertAlmostEqual(6.512201157564421e+09, impact.aai_agg, 5) self.assertTrue(np.isclose(6.512201157564421e+09, impact.aai_agg))
def test_ref_value_insure_pass(self): """Test result against reference value""" # Read demo entity values # Set the entity default file to the demo one ent = Entity() ent.read_excel(ENT_DEMO_TODAY) ent.check() # Read default hazard file hazard = Hazard('TC') hazard.read_mat(HAZ_TEST_MAT) # Create impact object impact = Impact() impact.at_event = np.zeros(hazard.intensity.shape[0]) impact.eai_exp = np.zeros(len(ent.exposures.value)) impact.tot_value = 0 # Assign centroids to exposures ent.exposures.assign_centroids(hazard) # Compute impact for 6th exposure iexp = 5 # Take its impact function imp_id = ent.exposures.if_TC[iexp] imp_fun = ent.impact_funcs.get_func(hazard.tag.haz_type, imp_id) # Compute insure_flag = True impact._exp_impact(np.array([iexp]), ent.exposures, hazard, imp_fun, insure_flag) self.assertEqual(impact.eai_exp.size, ent.exposures.shape[0]) self.assertEqual(impact.at_event.size, hazard.intensity.shape[0]) events_pos = hazard.intensity[:, ent.exposures.centr_TC[iexp]].nonzero( )[0] res_exp = np.zeros((ent.exposures.shape[0])) res_exp[iexp] = np.sum(impact.at_event[events_pos] * hazard.frequency[events_pos]) self.assertTrue(np.array_equal(res_exp, impact.eai_exp)) self.assertEqual(0, impact.at_event[12]) # Check first 3 values self.assertEqual(0, impact.at_event[12]) self.assertEqual(0, impact.at_event[41]) self.assertEqual(1.0626600695059455e+06, impact.at_event[44]) # Check intermediate values self.assertEqual(0, impact.at_event[6281]) self.assertEqual(0, impact.at_event[4998]) self.assertEqual(0, impact.at_event[9527]) self.assertEqual(1.3318063850487845e+08, impact.at_event[7192]) self.assertEqual(4.667108555054083e+06, impact.at_event[8624]) # Check last 3 values self.assertEqual(0, impact.at_event[14349]) self.assertEqual(0, impact.at_event[14347]) self.assertEqual(0, impact.at_event[14309])
def test_impact_pass(self): """Plot impact exceedence frequency curves.""" myent = Entity() myent.read_excel(ENT_DEMO_TODAY) myent.exposures.check() myhaz = Hazard('TC') myhaz.read_mat(HAZ_DEMO_MAT) myimp = Impact() myimp.calc(myent.exposures, myent.impact_funcs, myhaz) ifc = myimp.calc_freq_curve() myfig, _ = ifc.plot() self.assertIn('Exceedance frequency curve',\ myfig._suptitle.get_text()) ifc2 = ImpactFreqCurve() ifc2.return_per = ifc.return_per ifc2.impact = 1.5e11 * np.ones(ifc2.return_per.size) ifc2.unit = '' ifc2.label = 'prove' ifc.plot_compare(ifc2)
def _calc_impact(self, new_exp, new_impfs, new_haz): """Compute impact and risk transfer of measure implemented over inputs. Parameters ---------- new_exp : climada.entity.Exposures exposures once measure applied new_ifs : climada.entity.ImpactFuncSet impact function set once measure applied new_haz : climada.hazard.Hazard hazard once measure applied Returns ------- : climada.engine.Impact """ from climada.engine.impact import Impact imp = Impact() imp.calc(new_exp, new_impfs, new_haz) return imp.calc_risk_transfer(self.risk_transf_attach, self.risk_transf_cover)
def test_local_exceedance_imp_pass(self): """Test calc local impacts per return period""" # Read default entity values ent = Entity.from_excel(ENT_DEMO_TODAY) ent.check() # Read default hazard file hazard = Hazard.from_mat(HAZ_TEST_MAT) # Create impact object impact = Impact() # Assign centroids to exposures ent.exposures.assign_centroids(hazard) # Compute the impact over the whole exposures impact.calc(ent.exposures, ent.impact_funcs, hazard, save_mat=True) # Compute the impact per return period over the whole exposures impact_rp = impact.local_exceedance_imp(return_periods=(10, 40)) self.assertIsInstance(impact_rp, np.ndarray) self.assertEqual(impact_rp.size, 2 * ent.exposures.gdf.value.size) self.assertAlmostEqual(np.max(impact_rp), 2916964966.388219, places=5) self.assertAlmostEqual(np.min(impact_rp), 444457580.131494, places=5)
def _calc_impact_measures(self, hazard, exposures, meas_set, imp_fun_set, when='future', risk_func=risk_aai_agg, save_imp=False): """Compute impact of each measure and transform it to input risk measurement. Set reference year from exposures value. Parameters: hazard (Hazard): hazard. exposures (Exposures): exposures. meas_set (MeasureSet): set of measures. imp_fun_set (ImpactFuncSet): set of impact functions. when (str, optional): 'present' or 'future'. The conditions that are being considered. risk_func (function, optional): function used to transform impact to a risk measurement. save_imp (bool, optional): activate if Impact of each measure is saved. Default: False. """ impact_meas = dict() # compute impact without measures LOGGER.debug('%s impact with no measure.', when) imp_tmp = Impact() imp_tmp.calc(exposures, imp_fun_set, hazard) impact_meas[NO_MEASURE] = dict() impact_meas[NO_MEASURE]['cost'] = (0, 0) impact_meas[NO_MEASURE]['risk'] = risk_func(imp_tmp) impact_meas[NO_MEASURE]['risk_transf'] = 0.0 impact_meas[NO_MEASURE]['efc'] = imp_tmp.calc_freq_curve() if save_imp: impact_meas[NO_MEASURE]['impact'] = imp_tmp # compute impact for each measure for measure in meas_set.get_measure(hazard.tag.haz_type): LOGGER.debug('%s impact of measure %s.', when, measure.name) imp_tmp, risk_transf = measure.calc_impact(exposures, imp_fun_set, hazard) impact_meas[measure.name] = dict() impact_meas[measure.name]['cost'] = ( measure.cost, measure.risk_transf_cost_factor) impact_meas[measure.name]['risk'] = risk_func(imp_tmp) impact_meas[measure.name]['risk_transf'] = risk_func(risk_transf) impact_meas[measure.name]['efc'] = imp_tmp.calc_freq_curve() if save_imp: impact_meas[measure.name]['impact'] = imp_tmp # if present reference provided save it if when == 'future': self.imp_meas_future = impact_meas else: self.imp_meas_present = impact_meas
def _calc_impact_measures(self, hazard, exposures, meas_set, imp_fun_set, when='future', risk_func=risk_aai_agg, save_imp=False): """Compute impact of each measure and transform it to input risk measurement. Set reference year from exposures value. Parameters ---------- hazard : climada.Hazard exposures : climada.entity.Exposures meas_set : climada.MeasureSet set of measures. imp_fun_set : ImpactFuncSet set of impact functions. when : str, optional 'present' or 'future'. The conditions that are being considered. risk_func : func, optional function describing risk measure given an Impact. Default: average annual impact (aggregated). save_imp : bool, optional activate if Impact of each measure is saved. Default: False. """ impact_meas = dict() # compute impact without measures LOGGER.debug('%s impact with no measure.', when) imp_tmp = Impact() imp_tmp.calc(exposures, imp_fun_set, hazard) impact_meas[NO_MEASURE] = dict() impact_meas[NO_MEASURE]['cost'] = (0, 0) impact_meas[NO_MEASURE]['risk'] = risk_func(imp_tmp) impact_meas[NO_MEASURE]['risk_transf'] = 0.0 impact_meas[NO_MEASURE]['efc'] = imp_tmp.calc_freq_curve() if save_imp: impact_meas[NO_MEASURE]['impact'] = imp_tmp # compute impact for each measure for measure in meas_set.get_measure(hazard.tag.haz_type): LOGGER.debug('%s impact of measure %s.', when, measure.name) imp_tmp, risk_transf = measure.calc_impact(exposures, imp_fun_set, hazard) impact_meas[measure.name] = dict() impact_meas[measure.name]['cost'] = (measure.cost, measure.risk_transf_cost_factor) impact_meas[measure.name]['risk'] = risk_func(imp_tmp) impact_meas[measure.name]['risk_transf'] = risk_func(risk_transf) impact_meas[measure.name]['efc'] = imp_tmp.calc_freq_curve() if save_imp: impact_meas[measure.name]['impact'] = imp_tmp # if present reference provided save it if when == 'future': self.imp_meas_future = impact_meas else: self.imp_meas_present = impact_meas
def plot_waterfall_accumulated(self, hazard, entity, ent_future, risk_func=risk_aai_agg, imp_time_depen=1, axis=None, **kwargs): """ Plot waterfall graph with accumulated values from present to future year. Call after calc() with save_imp=True. Provide same inputs as in calc. Parameters: hazard (Hazard): hazard entity (Entity): entity ent_future (Entity): entity in the future risk_func (func, optional): function describing risk measure given an Impact. Default: average annual impact (aggregated). imp_time_depen (float, optional): parameter which represent time evolution of impact. Default: 1 (linear). axis (matplotlib.axes._subplots.AxesSubplot, optional): axis to use kwargs (optional): arguments for bar matplotlib function, e.g. alpha=0.5 Returns: matplotlib.axes._subplots.AxesSubplot """ if not self.imp_meas_future or not self.imp_meas_present: LOGGER.error('Compute CostBenefit.calc() first') raise ValueError if ent_future.exposures.ref_year == entity.exposures.ref_year: LOGGER.error( 'Same reference years for future and present entities.') raise ValueError self.present_year = entity.exposures.ref_year self.future_year = ent_future.exposures.ref_year # current situation curr_risk = self.imp_meas_present[NO_MEASURE]['risk'] time_dep = self._time_dependency_array() risk_curr = self._npv_unaverted_impact(curr_risk, entity.disc_rates, time_dep) LOGGER.info('Current total risk at {:d}: {:.3e}'.format( self.future_year, risk_curr)) # changing future time_dep = self._time_dependency_array(imp_time_depen) # socio-economic dev imp = Impact() imp.calc(ent_future.exposures, ent_future.impact_funcs, hazard) risk_dev = self._npv_unaverted_impact(risk_func(imp), entity.disc_rates, time_dep, curr_risk) LOGGER.info('Total risk with development at {:d}: {:.3e}'.format( \ self.future_year, risk_dev)) # socioecon + cc risk_tot = self._npv_unaverted_impact(self.imp_meas_future[NO_MEASURE]['risk'], \ entity.disc_rates, time_dep, curr_risk) LOGGER.info('Total risk with development and climate change at {:d}: {:.3e}'.\ format(self.future_year, risk_tot)) # plot if not axis: _, axis = plt.subplots(1, 1) norm_fact, norm_name = _norm_values(curr_risk) axis.bar(1, risk_curr / norm_fact, **kwargs) axis.text(1, risk_curr/norm_fact, str(int(round(risk_curr/norm_fact))), \ horizontalalignment='center', verticalalignment='bottom', \ fontsize=12, color='k') axis.bar(2, height=(risk_dev - risk_curr) / norm_fact, bottom=risk_curr / norm_fact, **kwargs) axis.text(2, risk_curr/norm_fact + (risk_dev-risk_curr)/norm_fact/2, \ str(int(round((risk_dev-risk_curr)/norm_fact))), \ horizontalalignment='center', verticalalignment='center', fontsize=12, color='k') axis.bar(3, height=(risk_tot - risk_dev) / norm_fact, bottom=risk_dev / norm_fact, **kwargs) axis.text(3, risk_dev/norm_fact + (risk_tot-risk_dev)/norm_fact/2, \ str(int(round((risk_tot-risk_dev)/norm_fact))), \ horizontalalignment='center', verticalalignment='center', fontsize=12, color='k') axis.bar(4, height=risk_tot / norm_fact, **kwargs) axis.text(4, risk_tot/norm_fact, str(int(round(risk_tot/norm_fact))), \ horizontalalignment='center', verticalalignment='bottom', \ fontsize=12, color='k') axis.set_xticks(np.arange(4) + 1) axis.set_xticklabels(['Risk ' + str(self.present_year), \ 'Economic \ndevelopment', 'Climate \nchange', 'Risk ' + str(self.future_year)]) axis.set_ylabel('Impact (' + self.unit + ' ' + norm_name + ')') axis.set_title('Total accumulated impact from {:d} to {:d}'.format( \ self.present_year, self.future_year)) return axis
def plot_waterfall(hazard, entity, haz_future, ent_future, risk_func=risk_aai_agg, axis=None, **kwargs): """ Plot waterfall graph at future with given risk metric. Can be called before and after calc(). Parameters: hazard (Hazard): hazard entity (Entity): entity haz_future (Hazard): hazard in the future (future year provided at ent_future) ent_future (Entity): entity in the future risk_func (func, optional): function describing risk measure given an Impact. Default: average annual impact (aggregated). axis (matplotlib.axes._subplots.AxesSubplot, optional): axis to use kwargs (optional): arguments for bar matplotlib function, e.g. alpha=0.5 Returns: matplotlib.axes._subplots.AxesSubplot """ if ent_future.exposures.ref_year == entity.exposures.ref_year: LOGGER.error( 'Same reference years for future and present entities.') raise ValueError present_year = entity.exposures.ref_year future_year = ent_future.exposures.ref_year imp = Impact() imp.calc(entity.exposures, entity.impact_funcs, hazard) curr_risk = risk_func(imp) imp = Impact() imp.calc(ent_future.exposures, ent_future.impact_funcs, haz_future) fut_risk = risk_func(imp) if not axis: _, axis = plt.subplots(1, 1) norm_fact, norm_name = _norm_values(curr_risk) # current situation LOGGER.info('Risk at {:d}: {:.3e}'.format(present_year, curr_risk)) # changing future # socio-economic dev imp = Impact() imp.calc(ent_future.exposures, ent_future.impact_funcs, hazard) risk_dev = risk_func(imp) LOGGER.info('Risk with development at {:d}: {:.3e}'.format( future_year, risk_dev)) # socioecon + cc LOGGER.info('Risk with development and climate change at {:d}: {:.3e}'.\ format(future_year, fut_risk)) axis.bar(1, curr_risk / norm_fact, **kwargs) axis.text(1, curr_risk/norm_fact, str(int(round(curr_risk/norm_fact))), \ horizontalalignment='center', verticalalignment='bottom', \ fontsize=12, color='k') axis.bar(2, height=(risk_dev - curr_risk) / norm_fact, bottom=curr_risk / norm_fact, **kwargs) axis.text(2, curr_risk/norm_fact + (risk_dev-curr_risk)/norm_fact/2, \ str(int(round((risk_dev-curr_risk)/norm_fact))), \ horizontalalignment='center', verticalalignment='center', fontsize=12, color='k') axis.bar(3, height=(fut_risk - risk_dev) / norm_fact, bottom=risk_dev / norm_fact, **kwargs) axis.text(3, risk_dev/norm_fact + (fut_risk-risk_dev)/norm_fact/2, \ str(int(round((fut_risk-risk_dev)/norm_fact))), \ horizontalalignment='center', verticalalignment='center', fontsize=12, color='k') axis.bar(4, height=fut_risk / norm_fact, **kwargs) axis.text(4, fut_risk/norm_fact, str(int(round(fut_risk/norm_fact))), \ horizontalalignment='center', verticalalignment='bottom', \ fontsize=12, color='k') axis.set_xticks(np.arange(4) + 1) axis.set_xticklabels(['Risk ' + str(present_year), \ 'Economic \ndevelopment', 'Climate \nchange', 'Risk ' + str(future_year)]) axis.set_ylabel('Impact (' + imp.unit + ' ' + norm_name + ')') axis.set_title('Risk at {:d} and {:d}'.format(present_year, future_year)) return axis
def test_ref_value_rp_pass(self): """Test result against reference value with given return periods""" imp = Impact() imp.frequency = np.ones(10) * 6.211180124223603e-04 imp.at_event = np.zeros(10) imp.at_event[0] = 0 imp.at_event[1] = 0.400665463736549e9 imp.at_event[2] = 3.150330960044466e9 imp.at_event[3] = 3.715826406781887e9 imp.at_event[4] = 2.900244271902339e9 imp.at_event[5] = 0.778570745161971e9 imp.at_event[6] = 0.698736262566472e9 imp.at_event[7] = 0.381063674256423e9 imp.at_event[8] = 0.569142464157450e9 imp.at_event[9] = 0.467572545849132e9 imp.unit = 'USD' ifc = imp.calc_freq_curve(np.array([100, 500, 1000])) self.assertEqual(3, len(ifc.return_per)) self.assertEqual(100, ifc.return_per[0]) self.assertEqual(500, ifc.return_per[1]) self.assertEqual(1000, ifc.return_per[2]) self.assertEqual(3, len(ifc.impact)) self.assertEqual(0, ifc.impact[0]) self.assertEqual(2320408028.5695677, ifc.impact[1]) self.assertEqual(3287314329.129928, ifc.impact[2]) self.assertEqual('Exceedance frequency curve', ifc.label) self.assertEqual('USD', ifc.unit)
def test_risk_trans_pass(self): """Test calc_risk_transfer""" # Create impact object imp = Impact() imp.event_id = np.arange(10) imp.event_name = [0, 1, 2, 3, 4, 5, 6, 7, 8, 15] imp.date = np.arange(10) imp.coord_exp = np.array([[1, 2], [2, 3]]) imp.crs = DEF_CRS imp.eai_exp = np.array([1, 2]) imp.at_event = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 15]) imp.frequency = np.ones(10) / 5 imp.tot_value = 10 imp.aai_agg = 100 imp.unit = 'USD' imp.imp_mat = sparse.csr_matrix(np.empty((0, 0))) new_imp, imp_rt = imp.calc_risk_transfer(2, 10) self.assertEqual(new_imp.unit, imp.unit) self.assertEqual(new_imp.tot_value, imp.tot_value) self.assertTrue((new_imp.imp_mat == imp.imp_mat).toarray().all()) self.assertEqual(new_imp.event_name, imp.event_name) self.assertTrue(np.allclose(new_imp.event_id, imp.event_id)) self.assertTrue(np.allclose(new_imp.date, imp.date)) self.assertTrue(np.allclose(new_imp.frequency, imp.frequency)) self.assertTrue(np.allclose(new_imp.coord_exp, np.array([]))) self.assertTrue(np.allclose(new_imp.eai_exp, np.array([]))) self.assertTrue( np.allclose(new_imp.at_event, np.array([0, 1, 2, 2, 2, 2, 2, 2, 2, 5]))) self.assertAlmostEqual(new_imp.aai_agg, 4.0) self.assertEqual(imp_rt.unit, imp.unit) self.assertEqual(imp_rt.tot_value, imp.tot_value) self.assertTrue((imp_rt.imp_mat == imp.imp_mat).toarray().all()) self.assertEqual(imp_rt.event_name, imp.event_name) self.assertTrue(np.allclose(imp_rt.event_id, imp.event_id)) self.assertTrue(np.allclose(imp_rt.date, imp.date)) self.assertTrue(np.allclose(imp_rt.frequency, imp.frequency)) self.assertTrue(np.allclose(imp_rt.coord_exp, np.array([]))) self.assertTrue(np.allclose(imp_rt.eai_exp, np.array([]))) self.assertTrue( np.allclose(imp_rt.at_event, np.array([0, 0, 0, 1, 2, 3, 4, 5, 6, 10]))) self.assertAlmostEqual(imp_rt.aai_agg, 6.2)
def test_write_imp_mat(self): """Test write_excel_imp_mat function""" impact = Impact() impact.imp_mat = np.zeros((5, 4)) impact.imp_mat[0, :] = np.arange(4) impact.imp_mat[1, :] = np.arange(4) * 2 impact.imp_mat[2, :] = np.arange(4) * 3 impact.imp_mat[3, :] = np.arange(4) * 4 impact.imp_mat[4, :] = np.arange(4) * 5 impact.imp_mat = sparse.csr_matrix(impact.imp_mat) file_name = os.path.join(DATA_FOLDER, 'test_imp_mat') impact.write_sparse_csr(file_name) read_imp_mat = Impact().read_sparse_csr(file_name + '.npz') for irow in range(5): self.assertTrue( np.array_equal( np.array(read_imp_mat[irow, :].toarray()).reshape(-1), np.array(impact.imp_mat[irow, :].toarray()).reshape(-1)))
def test_write_read_exp_test(self): """Test result against reference value""" # Create impact object num_ev = 5 num_exp = 10 imp_write = Impact() imp_write.tag = { 'exp': Tag('file_exp.p', 'descr exp'), 'haz': TagHaz('TC', 'file_haz.p', 'descr haz'), 'if_set': Tag() } imp_write.event_id = np.arange(num_ev) imp_write.event_name = [ 'event_' + str(num) for num in imp_write.event_id ] imp_write.date = np.ones(num_ev) imp_write.coord_exp = np.zeros((num_exp, 2)) imp_write.coord_exp[:, 0] = 1.5 imp_write.coord_exp[:, 1] = 2.5 imp_write.eai_exp = np.arange(num_exp) * 100 imp_write.at_event = np.arange(num_ev) * 50 imp_write.frequency = np.ones(num_ev) * 0.1 imp_write.tot_value = 1000 imp_write.aai_agg = 1001 imp_write.unit = 'USD' file_name = os.path.join(DATA_FOLDER, 'test.csv') imp_write.write_csv(file_name) imp_read = Impact() imp_read.read_csv(file_name) self.assertTrue(np.array_equal(imp_write.event_id, imp_read.event_id)) self.assertTrue(np.array_equal(imp_write.date, imp_read.date)) self.assertTrue(np.array_equal(imp_write.coord_exp, imp_read.coord_exp)) self.assertTrue(np.array_equal(imp_write.eai_exp, imp_read.eai_exp)) self.assertTrue(np.array_equal(imp_write.at_event, imp_read.at_event)) self.assertTrue(np.array_equal(imp_write.frequency, imp_read.frequency)) self.assertEqual(imp_write.tot_value, imp_read.tot_value) self.assertEqual(imp_write.aai_agg, imp_read.aai_agg) self.assertEqual(imp_write.unit, imp_read.unit) self.assertEqual( 0, len([ i for i, j in zip(imp_write.event_name, imp_read.event_name) if i != j ])) self.assertIsInstance(imp_read.crs, dict)
def test_ref_value_pass(self): """Test result against reference value""" imp = Impact() imp.frequency = np.ones(10) * 6.211180124223603e-04 imp.at_event = np.zeros(10) imp.at_event[0] = 0 imp.at_event[1] = 0.400665463736549e9 imp.at_event[2] = 3.150330960044466e9 imp.at_event[3] = 3.715826406781887e9 imp.at_event[4] = 2.900244271902339e9 imp.at_event[5] = 0.778570745161971e9 imp.at_event[6] = 0.698736262566472e9 imp.at_event[7] = 0.381063674256423e9 imp.at_event[8] = 0.569142464157450e9 imp.at_event[9] = 0.467572545849132e9 imp.unit = 'USD' ifc = imp.calc_freq_curve() self.assertEqual(10, len(ifc.return_per)) self.assertEqual(1610.0000000000000, ifc.return_per[9]) self.assertEqual(805.00000000000000, ifc.return_per[8]) self.assertEqual(536.66666666666663, ifc.return_per[7]) self.assertEqual(402.500000000000, ifc.return_per[6]) self.assertEqual(322.000000000000, ifc.return_per[5]) self.assertEqual(268.33333333333331, ifc.return_per[4]) self.assertEqual(230.000000000000, ifc.return_per[3]) self.assertEqual(201.250000000000, ifc.return_per[2]) self.assertEqual(178.88888888888889, ifc.return_per[1]) self.assertEqual(161.000000000000, ifc.return_per[0]) self.assertEqual(10, len(ifc.impact)) self.assertEqual(3.715826406781887e9, ifc.impact[9]) self.assertEqual(3.150330960044466e9, ifc.impact[8]) self.assertEqual(2.900244271902339e9, ifc.impact[7]) self.assertEqual(0.778570745161971e9, ifc.impact[6]) self.assertEqual(0.698736262566472e9, ifc.impact[5]) self.assertEqual(0.569142464157450e9, ifc.impact[4]) self.assertEqual(0.467572545849132e9, ifc.impact[3]) self.assertEqual(0.400665463736549e9, ifc.impact[2]) self.assertEqual(0.381063674256423e9, ifc.impact[1]) self.assertEqual(0, ifc.impact[0]) self.assertEqual('Exceedance frequency curve', ifc.label) self.assertEqual('USD', ifc.unit)
def test_impact_year_set_sum(self): """Test result against reference value with given events""" imp = Impact() imp.frequency = np.ones(10) * 6.211180124223603e-04 imp.at_event = np.zeros(10) imp.at_event[0] = 0 imp.at_event[1] = 0.400665463736549e9 imp.at_event[2] = 3.150330960044466e9 imp.at_event[3] = 3.715826406781887e9 imp.at_event[4] = 2.900244271902339e9 imp.at_event[5] = 0.778570745161971e9 imp.at_event[6] = 0.698736262566472e9 imp.at_event[7] = 0.381063674256423e9 imp.at_event[8] = 0.569142464157450e9 imp.at_event[9] = 0.467572545849132e9 imp.unit = 'USD' imp.date = np.array([ 732801, 716160, 718313, 712468, 732802, 729285, 732931, 715419, 722404, 718351 ]) iys_all = imp.calc_impact_year_set() iys = imp.calc_impact_year_set(all_years=False) iys_all_yr = imp.calc_impact_year_set(year_range=(1975, 2000)) iys_yr = imp.calc_impact_year_set(all_years=False, year_range=[1975, 2000]) iys_all_yr_1940 = imp.calc_impact_year_set(all_years=True, year_range=[1940, 2000]) self.assertEqual(np.around(sum([iys[year] for year in iys])), np.around(sum(imp.at_event))) self.assertEqual(sum([iys[year] for year in iys]), sum([iys_all[year] for year in iys_all])) self.assertEqual(len(iys), 7) self.assertEqual(len(iys_all), 57) self.assertIn(1951 and 1959 and 2007, iys_all) self.assertTrue(iys_all[1959] > 0) self.assertAlmostEqual(3598980534.468811, iys_all[2007]) self.assertEqual(iys[1978], iys_all[1978]) self.assertAlmostEqual(iys[1951], imp.at_event[3]) # year range (yr): self.assertEqual(len(iys_yr), 2) self.assertEqual(len(iys_all_yr), 26) self.assertEqual(sum([iys_yr[year] for year in iys_yr]), sum([iys_all_yr[year] for year in iys_all_yr])) self.assertIn(1997 and 1978, iys_yr) self.assertFalse(2007 in iys_yr) self.assertFalse(1959 in iys_yr) self.assertEqual(len(iys_all_yr_1940), 61)
def dummy_impact(): imp = Impact() imp.event_id = np.arange(6) imp.event_name = [0, 1, 'two', 'three', 30, 31] imp.date = np.arange(6) imp.coord_exp = np.array([[1, 2], [1.5, 2.5]]) imp.crs = DEF_CRS imp.eai_exp = np.array([7.2, 7.2]) imp.at_event = np.array([0, 2, 4, 6, 60, 62]) imp.frequency = np.array([1 / 6, 1 / 6, 1, 1, 1 / 30, 1 / 30]) imp.tot_value = 7 imp.aai_agg = 14.4 imp.unit = 'USD' imp.imp_mat = sparse.csr_matrix( np.array([[0, 0], [1, 1], [2, 2], [3, 3], [30, 30], [31, 31]])) return imp