Skip to content

Commit 7f74ea4

Browse files
authored
Improve impact calc error messages when there is a mismatch of impf ids between exposures and impfset (#863)
* Add error handling for missmatching impf ids between exposures and impfset in ImpactCalc.impact() * Clarify error message for handling of mismatching impf ids between impfset and exposures in ImpactCalc.impact() * Add unit test for error handling of mismatchin impf ids between impf set and exposures in ImpactCalc.impact() * Make code compliant with PEP8 * Change ambiguous variable names * Add impact function in the impf set but not in the exposure for the test_error_handling_mismatch_impf_ids * Add name to authors's list * Add changes to changelog * Use assertRaises instead of assertEqual to test the error handling * Refine error message so that it provides users with the ids of missing impfs * Initiate dummy impf in testing function directly setting its attributes * Correct for pylint warnings for too long lines --------- Co-authored-by: luseverin <[email protected]>
1 parent 9d549e9 commit 7f74ea4

File tree

4 files changed

+39
-2
lines changed

4 files changed

+39
-2
lines changed

AUTHORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@
3232
* Kam Lam Yeung
3333
* Sarah Hülsen
3434
* Timo Schmid
35+
* Luca Severino

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Code freeze date: YYYY-MM-DD
1414

1515
### Changed
1616

17+
- Improved error messages produced by `ImpactCalc.impact()` in case impact function in the exposures is not found in impf_set [#863](https://github.com/CLIMADA-project/climada_python/pull/863)
18+
1719
### Fixed
1820

1921
### Deprecated

climada/engine/impact_calc.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def impact(self, save_mat=True, assign_centroids=True,
112112
apply_deductible_to_mat : apply deductible to impact matrix
113113
apply_cover_to_mat : apply cover to impact matrix
114114
"""
115-
# check for compability of exposures and hazard type
115+
# check for compatibility of exposures and hazard type
116116
if all(name not in self.exposures.gdf.columns for
117117
name in ['if_', f'if_{self.hazard.haz_type}',
118118
'impf_', f'impf_{self.hazard.haz_type}']):
@@ -121,14 +121,28 @@ def impact(self, save_mat=True, assign_centroids=True,
121121
f"for hazard type {self.hazard.haz_type} in exposures."
122122
)
123123

124-
# check for compability of impact function and hazard type
124+
# check for compatibility of impact function and hazard type
125125
if not self.impfset.get_func(haz_type=self.hazard.haz_type):
126126
raise AttributeError(
127127
"Impact calculation not possible. No impact functions found "
128128
f"for hazard type {self.hazard.haz_type} in impf_set."
129129
)
130130

131131
impf_col = self.exposures.get_impf_column(self.hazard.haz_type)
132+
known_impact_functions = self.impfset.get_ids(haz_type=self.hazard.haz_type)
133+
134+
# check for compatibility of impact function id between impact function set and exposure
135+
if not all(self.exposures.gdf[impf_col].isin(known_impact_functions)):
136+
unknown_impact_functions = list(self.exposures.gdf[
137+
~self.exposures.gdf[impf_col].isin(known_impact_functions)
138+
][impf_col].drop_duplicates().astype(int).astype(str))
139+
raise ValueError(
140+
f"The associated impact function(s) with id(s) "
141+
f"{', '.join(unknown_impact_functions)} have no match in impact function set for"
142+
f" hazard type \'{self.hazard.haz_type}\'.\nPlease make sure that all exposure "
143+
"points are associated with an impact function that is included in the impact "
144+
"function set.")
145+
132146
exp_gdf = self.minimal_exp_gdf(impf_col, assign_centroids, ignore_cover, ignore_deductible)
133147
if exp_gdf.size == 0:
134148
return self._return_empty(save_mat)

climada/engine/test/test_impact_calc.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,26 @@ def test_error_handling_mismatch_haz_type(self):
135135
except Exception as e:
136136
self.assertEqual(str(e), "Impact calculation not possible. No impact "
137137
"functions found for hazard type TC in impf_set.")
138+
def test_error_handling_mismatch_impf_ids(self):
139+
"""Test error handling in case impf ids in exposures
140+
does not appear in impf_set"""
141+
haz = Hazard('TC')
142+
exp = Exposures()
143+
exp.gdf.loc[0,'impf_TC'] = 1
144+
exp.gdf.loc[1,'impf_TC'] = 2
145+
impf_exp = ImpactFunc(haz_type='TC', id=1)
146+
impf_noexp = deepcopy(impf_exp)
147+
impf_noexp.id = 3
148+
impfset = ImpactFuncSet([impf_exp, impf_noexp])
149+
150+
with self.assertRaises(ValueError) as cm:
151+
ImpactCalc(exp, impfset, haz).impact()
152+
the_exception = cm.exception
153+
self.assertEqual(the_exception.args[0],
154+
"The associated impact function(s) with id(s) 2 have no match in "
155+
"impact function set for hazard type \'TC\'.\nPlease make sure "
156+
"that all exposure points are associated with an impact "
157+
"function that is included in the impact function set.")
138158

139159
def test_calc_impact_TC_pass(self):
140160
"""Test compute impact"""

0 commit comments

Comments
 (0)