Skip to content

Commit 0cb35ca

Browse files
Merge pull request #1066 from CLIMADA-project/hotfix/assign_centroids_in_costbenefit
Hotfix: assign centroids in cost benefit impact calculation if in new exposure no centroids were assigned
2 parents a15be70 + bd97cf4 commit 0cb35ca

File tree

3 files changed

+77
-13
lines changed

3 files changed

+77
-13
lines changed

climada/engine/cost_benefit.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,9 +1079,7 @@ def _calc_impact_measures(
10791079
# compute impact for each measure
10801080
for measure in meas_set.get_measure(hazard.haz_type):
10811081
LOGGER.debug("%s impact of measure %s.", when, measure.name)
1082-
imp_tmp, risk_transf = measure.calc_impact(
1083-
exposures, imp_fun_set, hazard, assign_centroids=False
1084-
)
1082+
imp_tmp, risk_transf = measure.calc_impact(exposures, imp_fun_set, hazard)
10851083
impact_meas[measure.name] = dict()
10861084
impact_meas[measure.name]["cost"] = (
10871085
measure.cost,

climada/engine/test/test_cost_benefit.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
)
3636
from climada.entity.disc_rates import DiscRates
3737
from climada.entity.entity_def import Entity
38+
from climada.entity.measures import Measure
39+
from climada.entity.measures.base import LOGGER as ILOG
3840
from climada.hazard.base import Hazard
3941
from climada.test import get_test_file
4042
from climada.util.api_client import Client
@@ -1119,6 +1121,66 @@ def test_remove_measure(self):
11191121
self.assertEqual(len(cost_ben.cost_ben_ratio), 3)
11201122
self.assertEqual(len(cost_ben.benefit), 3)
11211123

1124+
def test_measure_exposure_no_centroids(self):
1125+
"""Test centroids assigned if no centroids were assigned in Measure Exposures object"""
1126+
hazard = Hazard.from_hdf5(HAZ_TEST_TC)
1127+
entity = Entity.from_excel(ENT_DEMO_TODAY)
1128+
entity.check()
1129+
entity.exposures.ref_year = 2018
1130+
1131+
# test that warning is not raised when centroid are assigned
1132+
try:
1133+
with self.assertLogs(ILOG, level="WARNING") as logs:
1134+
cost_ben = CostBenefit()
1135+
cost_ben.calc(
1136+
hazard,
1137+
entity,
1138+
future_year=2040,
1139+
risk_func=risk_aai_agg,
1140+
imp_time_depen=None,
1141+
save_imp=True,
1142+
)
1143+
for log in logs.output:
1144+
self.assertNotIn(
1145+
"No assigned hazard centroids in exposure object after",
1146+
log,
1147+
"Centroids are already assinged in Measure Exposure object"
1148+
"and should not be reassigned.",
1149+
)
1150+
except AssertionError as e:
1151+
if "no logs" in str(e).lower():
1152+
pass
1153+
else:
1154+
raise
1155+
1156+
# add measure with exposure without assigned centroids
1157+
exp_no_assigned_centroids = entity.exposures.copy()
1158+
exp_no_assigned_centroids.data = entity.exposures.data.drop(
1159+
columns=["centr_TC"]
1160+
)
1161+
entity.measures.append(
1162+
Measure(
1163+
name="no centroids",
1164+
haz_type="TC",
1165+
exposures_set=exp_no_assigned_centroids,
1166+
)
1167+
)
1168+
1169+
# test if warning is raised
1170+
with self.assertLogs(ILOG, level="WARNING") as logs:
1171+
cost_ben = CostBenefit()
1172+
cost_ben.calc(
1173+
hazard,
1174+
entity,
1175+
future_year=2040,
1176+
risk_func=risk_aai_agg,
1177+
imp_time_depen=None,
1178+
save_imp=True,
1179+
)
1180+
self.assertIn(
1181+
"No assigned hazard centroids in exposure object after", logs.output[0]
1182+
)
1183+
11221184

11231185
class TestCalc(unittest.TestCase):
11241186
"""Test calc"""

climada/entity/measures/base.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ def check(self):
179179
u_check.size(2, self.mdd_impact, "Measure.mdd_impact")
180180
u_check.size(2, self.paa_impact, "Measure.paa_impact")
181181

182-
def calc_impact(self, exposures, imp_fun_set, hazard, assign_centroids=True):
182+
def calc_impact(self, exposures, imp_fun_set, hazard):
183183
"""
184184
Apply measure and compute impact and risk transfer of measure
185185
implemented over inputs.
@@ -192,12 +192,6 @@ def calc_impact(self, exposures, imp_fun_set, hazard, assign_centroids=True):
192192
impact function set instance
193193
hazard : climada.hazard.Hazard
194194
hazard instance
195-
assign_centroids : bool, optional
196-
indicates whether centroids are assigned to the self.exposures object.
197-
Centroids assignment is an expensive operation; set this to ``False`` to save
198-
computation time if the hazards' centroids are already assigned to the exposures
199-
object.
200-
Default: True
201195
202196
Returns
203197
-------
@@ -206,7 +200,17 @@ def calc_impact(self, exposures, imp_fun_set, hazard, assign_centroids=True):
206200
"""
207201

208202
new_exp, new_impfs, new_haz = self.apply(exposures, imp_fun_set, hazard)
209-
return self._calc_impact(new_exp, new_impfs, new_haz, assign_centroids)
203+
# assign centroids if missing
204+
if new_haz.centr_exp_col not in new_exp.gdf.columns:
205+
LOGGER.warning(
206+
"No assigned hazard centroids in exposure object after the "
207+
"application of the measure. The centroids will be assigned during impact "
208+
"calculation. This is potentiall costly. To silence this warning, make sure "
209+
"that centroids are assigned to all exposures."
210+
)
211+
new_exp.assign_centroids(new_haz)
212+
213+
return self._calc_impact(new_exp, new_impfs, new_haz)
210214

211215
def apply(self, exposures, imp_fun_set, hazard):
212216
"""
@@ -246,7 +250,7 @@ def apply(self, exposures, imp_fun_set, hazard):
246250

247251
return new_exp, new_impfs, new_haz
248252

249-
def _calc_impact(self, new_exp, new_impfs, new_haz, assign_centroids):
253+
def _calc_impact(self, new_exp, new_impfs, new_haz):
250254
"""Compute impact and risk transfer of measure implemented over inputs.
251255
252256
Parameters
@@ -267,7 +271,7 @@ def _calc_impact(self, new_exp, new_impfs, new_haz, assign_centroids):
267271
)
268272

269273
imp = ImpactCalc(new_exp, new_impfs, new_haz).impact(
270-
save_mat=False, assign_centroids=assign_centroids
274+
save_mat=False, assign_centroids=False
271275
)
272276
return imp.calc_risk_transfer(self.risk_transf_attach, self.risk_transf_cover)
273277

0 commit comments

Comments
 (0)