Skip to content

Commit a3d189a

Browse files
Merge pull request #675 from CLIMADA-project/feature/haz_type_in_step_impf
Feature/haz type in step impf
2 parents 20754b1 + 5ff0f7d commit a3d189a

File tree

4 files changed

+45
-15
lines changed

4 files changed

+45
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Removed:
2828
[#602](https://github.com/CLIMADA-project/climada_python/pull/602)
2929
- Modified the method to disaggregate lines in the `lines_polys_handler` utility module in order to better conserve the total length of all lines on average [#679](https://github.com/CLIMADA-project/climada_python/pull/679).
3030
- Added test for non-default impact function id in the `lines_polys_handler` [#676](https://github.com/CLIMADA-project/climada_python/pull/676)
31+
- The sigmoid and step impact functions now require the user to define the hazard type. [#675](https://github.com/CLIMADA-project/climada_python/pull/675)
3132

3233
### Fixed
3334

climada/entity/impact_funcs/base.py

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def __init__(
9696
self.mdd = mdd if mdd is not None else np.array([])
9797
self.paa = paa if paa is not None else np.array([])
9898

99-
def calc_mdr(self, inten):
99+
def calc_mdr(self, inten: Union[float, np.ndarray]) -> np.ndarray:
100100
"""Interpolate impact function to a given intensity.
101101
102102
Parameters
@@ -162,7 +162,14 @@ def check(self):
162162
return
163163

164164
@classmethod
165-
def from_step_impf(cls, intensity, mdd=(0, 1), paa=(1, 1), impf_id=1):
165+
def from_step_impf(
166+
cls,
167+
intensity: tuple[float, float, float],
168+
haz_type: str,
169+
mdd: tuple[float, float] = (0, 1),
170+
paa: tuple[float, float] = (1, 1),
171+
impf_id: int = 1,
172+
**kwargs):
166173

167174
""" Step function type impact function.
168175
@@ -176,12 +183,16 @@ def from_step_impf(cls, intensity, mdd=(0, 1), paa=(1, 1), impf_id=1):
176183
----------
177184
intensity: tuple(float, float, float)
178185
tuple of 3-intensity numbers: (minimum, threshold, maximum)
186+
haz_type: str
187+
the reference string for the hazard (e.g., 'TC', 'RF', 'WS', ...)
179188
mdd: tuple(float, float)
180189
(min, max) mdd values. The default is (0, 1)
181190
paa: tuple(float, float)
182191
(min, max) paa values. The default is (1, 1)
183192
impf_id : int, optional, default=1
184193
impact function id
194+
kwargs :
195+
keyword arguments passed to ImpactFunc()
185196
186197
Return
187198
------
@@ -196,7 +207,8 @@ def from_step_impf(cls, intensity, mdd=(0, 1), paa=(1, 1), impf_id=1):
196207
mdd_min, mdd_max = mdd
197208
mdd = np.array([mdd_min, mdd_min, mdd_max, mdd_max])
198209

199-
return cls(id=impf_id, intensity=intensity, mdd=mdd, paa=paa)
210+
return cls(haz_type=haz_type, id=impf_id,
211+
intensity=intensity, mdd=mdd, paa=paa, **kwargs)
200212

201213
def set_step_impf(self, *args, **kwargs):
202214
"""This function is deprecated, use ImpactFunc.from_step_impf instead."""
@@ -205,7 +217,15 @@ def set_step_impf(self, *args, **kwargs):
205217
self.__dict__ = ImpactFunc.from_step_impf(*args, **kwargs).__dict__
206218

207219
@classmethod
208-
def from_sigmoid_impf(cls, intensity, L, k, x0, if_id=1):
220+
def from_sigmoid_impf(
221+
cls,
222+
intensity: tuple[float, float, float],
223+
L: float,
224+
k: float,
225+
x0: float,
226+
haz_type: str,
227+
impf_id: int = 1,
228+
**kwargs):
209229
"""Sigmoid type impact function hinging on three parameter.
210230
211231
This type of impact function is very flexible for any sort of study,
@@ -228,20 +248,25 @@ def from_sigmoid_impf(cls, intensity, L, k, x0, if_id=1):
228248
"slope" of sigmoid
229249
x0 : float
230250
intensity value where f(x)==L/2
231-
if_id : int, optional, default=1
251+
haz_type: str
252+
the reference string for the hazard (e.g., 'TC', 'RF', 'WS', ...)
253+
impf_id : int, optional, default=1
232254
impact function id
255+
kwargs :
256+
keyword arguments passed to ImpactFunc()
233257
234258
Return
235259
------
236260
impf : climada.entity.impact_funcs.ImpactFunc
237-
Step impact function
261+
Sigmoid impact function
238262
"""
239263
inten_min, inten_max, inten_step = intensity
240264
intensity = np.arange(inten_min, inten_max, inten_step)
241265
paa = np.ones(len(intensity))
242266
mdd = L / (1 + np.exp(-k * (intensity - x0)))
243267

244-
return cls(id=if_id, intensity=intensity, paa=paa, mdd=mdd)
268+
return cls(haz_type=haz_type, id=impf_id, intensity=intensity,
269+
paa=paa, mdd=mdd, **kwargs)
245270

246271
def set_sigmoid_impf(self, *args, **kwargs):
247272
"""This function is deprecated, use LitPop.from_countries instead."""

climada/entity/impact_funcs/test/test_base.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,27 +36,31 @@ def test_calc_mdr_pass(self):
3636
new_inten = 17.2
3737
self.assertEqual(imp_fun.calc_mdr(new_inten), 0.029583999999999996)
3838

39-
def test_set_step(self):
39+
def test_from_step(self):
4040
"""Check default impact function: step function"""
4141
inten = (0, 5, 10)
42-
imp_fun = ImpactFunc.from_step_impf(inten)
42+
imp_fun = ImpactFunc.from_step_impf(
43+
intensity=inten, haz_type='TC', impf_id=2)
4344
self.assertTrue(np.array_equal(imp_fun.paa, np.ones(4)))
4445
self.assertTrue(np.array_equal(imp_fun.mdd, np.array([0, 0, 1, 1])))
4546
self.assertTrue(np.array_equal(imp_fun.intensity, np.array([0, 5, 5, 10])))
47+
self.assertEqual(imp_fun.haz_type, 'TC')
48+
self.assertEqual(imp_fun.id, 2)
4649

47-
def test_set_sigmoid(self):
50+
51+
def test_from_sigmoid(self):
4852
"""Check default impact function: sigmoid function"""
4953
inten = (0, 100, 5)
50-
imp_fun = ImpactFunc.from_sigmoid_impf(inten, L=1.0, k=2., x0=50.)
54+
imp_fun = ImpactFunc.from_sigmoid_impf(
55+
inten, L=1.0, k=2., x0=50., haz_type='RF', impf_id=2)
5156
self.assertTrue(np.array_equal(imp_fun.paa, np.ones(20)))
5257
self.assertEqual(imp_fun.mdd[10], 0.5)
5358
self.assertEqual(imp_fun.mdd[-1], 1.0)
5459
self.assertTrue(np.array_equal(imp_fun.intensity, np.arange(0, 100, 5)))
60+
self.assertEqual(imp_fun.haz_type, 'RF')
61+
self.assertEqual(imp_fun.id, 2)
5562

5663
# Execute Tests
5764
if __name__ == "__main__":
5865
TESTS = unittest.TestLoader().loadTestsFromTestCase(TestInterpolation)
5966
unittest.TextTestRunner(verbosity=2).run(TESTS)
60-
61-
62-

climada/hazard/test/test_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1392,7 +1392,7 @@ def test_clear_pool(self):
13921392
def dummy_step_impf(haz):
13931393
from climada.entity import ImpactFunc
13941394
intensity = (0, 1, haz.intensity.max())
1395-
impf = ImpactFunc.from_step_impf(intensity)
1395+
impf = ImpactFunc.from_step_impf(intensity, haz_type=haz.tag.haz_type)
13961396
return impf
13971397

13981398
class TestImpactFuncs(unittest.TestCase):

0 commit comments

Comments
 (0)