Skip to content

Commit 19c482a

Browse files
implemented changes suggested by Sarah H
1 parent de81342 commit 19c482a

File tree

6 files changed

+89
-87
lines changed

6 files changed

+89
-87
lines changed

climada/engine/impact.py

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -473,10 +473,9 @@ def local_exceedance_impact(
473473
self,
474474
return_periods=(25, 50, 100, 250),
475475
method = 'interpolate',
476-
impact_cutoff=0,
476+
min_impact=0,
477477
log_frequency=True,
478-
log_impact=True,
479-
extrapolation = True
478+
log_impact=True
480479
):
481480
"""Compute local exceedance impact for given return periods. The default method
482481
is fitting the ordered impacts per centroid to the corresponding cummulated
@@ -488,24 +487,22 @@ def local_exceedance_impact(
488487
User-specified return periods for which the exceedance intensity should be calculated
489488
locally (at each centroid). Defaults to (25, 50, 100, 250).
490489
method : str
491-
Method to interpolate to new return periods. Currently available are "interpolate" and
492-
"stepfunction". Defauls to "interpolate".
493-
impact_cutoff : float, optional
494-
Minimal threshold to filter the impact. Defaults to 0.
490+
Method to interpolate to new return periods. Currently available are "interpolate",
491+
"extrapolate" and "stepfunction". If set to "interpolate" or "stepfunction",
492+
return periods larger than the Impact object's observed local return periods will be
493+
assigned the largest local impact, and return periods smaller than the Impact object's
494+
observed local return periods will be assigned 0. If set to "extrapolate", local
495+
exceedance impacts will be extrapolated (and interpolated). Defauls to "interpolate".
496+
min_impact : float, optional
497+
Minimum threshold to filter the impact. Defaults to 0.
495498
log_frequency : bool, optional
496-
This parameter is only used if method is set to "interpolate". If set to True,
497-
(cummulative) frequency values are converted to log scale before inter- and
499+
This parameter is only used if method is set to "extrapolate" or "interpolate". If set
500+
to True, (cummulative) frequency values are converted to log scale before inter- and
498501
extrapolation. Defaults to True.
499502
log_impact : bool, optional
500-
This parameter is only used if method is set to "interpolate". If set to True,
501-
impact values are converted to log scale before inter- and extrapolation.
503+
This parameter is only used if method is set to "extrapolate" or "interpolate". If set
504+
to True, impact values are converted to log scale before inter- and extrapolation.
502505
Defaults to True.
503-
extrapolation : bool, optional
504-
This parameter is only used if method is set to "interpolate". If set to True, local
505-
exceedance impacts will be extrapolated. If set to False, return periods larger than
506-
the Impact object's observed local return periods will be assigned the largest
507-
local impact, and return periods smaller than the Impact object's observed local
508-
return periods will be assigned 0. Defaults to True.
509506
510507
Returns
511508
-------
@@ -552,16 +549,17 @@ def local_exceedance_impact(
552549

553550
# fit intensities to cummulative frequencies
554551
frequency = np.cumsum(frequency[::-1])[::-1]
555-
if method == 'interpolate':
556-
imp_stats[:,i] = u_interp.interpolate_ev(
557-
1/np.array(return_periods), frequency[::-1], impact[::-1], logx=log_frequency,
558-
logy=log_impact, y_threshold=impact_cutoff, extrapolation=extrapolation, y_asymptotic=0.
559-
)
560-
elif method == 'stepfunction':
552+
if method == 'stepfunction':
561553
imp_stats[:,i] = u_interp.stepfunction_ev(
562-
1/np.array(return_periods), frequency[::-1], impact[::-1], y_threshold=impact_cutoff,
554+
1/np.array(return_periods), frequency[::-1], impact[::-1], y_threshold=min_impact,
563555
y_asymptotic=0.
564556
)
557+
elif method == 'extrapolate' or method == 'interpolate':
558+
extrapolation = (method == 'extrapolate')
559+
imp_stats[:,i] = u_interp.interpolate_ev(
560+
1/np.array(return_periods), frequency[::-1], impact[::-1], logx=log_frequency,
561+
logy=log_impact, y_threshold=min_impact, extrapolation=extrapolation, y_asymptotic=0.
562+
)
565563
else:
566564
raise ValueError(f"Unknown method: {method}")
567565

@@ -584,8 +582,11 @@ def local_exceedance_imp(
584582
return_periods=(25, 50, 100, 250)
585583
):
586584
"""This function is deprecated, use Impact.local_exceedance_impact instead."""
587-
LOGGER.warning("The use of Impact.local_exceedance_imp is deprecated."
588-
"Use Impact.local_exceedance_impact instead.")
585+
LOGGER.warning(
586+
"The use of Impact.local_exceedance_imp is deprecated. Use "
587+
"Impact.local_exceedance_impact instead. Some errors in the previous calculation "
588+
"in Impact.local_exceedance_imp have been corrected. To reproduce data with the "
589+
"previous calculation, use CLIMADA v5.0.0 or less.")
589590

590591
return self.local_exceedance_impact(return_periods)[0].values[:,1:].T.astype(float)
591592

climada/engine/test/test_impact.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ def test_local_exceedance_impact(self):
517517
# fourth centroid has intensities 1,2,3,4 with cum frequencies 4,3,2,1
518518
# testing at frequencies 5, 2, 1, 0.5
519519
impact_stats, _, _ = impact.local_exceedance_impact(
520-
return_periods=(.2, .5, 1, 2), log_frequency=False, log_impact=False)
520+
return_periods=(.2, .5, 1, 2), method="extrapolate", log_frequency=False, log_impact=False)
521521
np.testing.assert_allclose(
522522
impact_stats.values[:,1:].astype(float),
523523
np.array([

climada/hazard/base.py

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -452,10 +452,9 @@ def local_exceedance_intensity(
452452
self,
453453
return_periods=(25, 50, 100, 250),
454454
method='interpolate',
455-
intensity_cutoff=None,
455+
min_intensity=None,
456456
log_frequeny=True,
457-
log_intensity=True,
458-
extrapolation=True
457+
log_intensity=True
459458
):
460459
"""Compute local exceedance intensity for given return periods. The default method
461460
is fitting the ordered intensitites per centroid to the corresponding cummulated
@@ -467,10 +466,15 @@ def local_exceedance_intensity(
467466
User-specified return periods for which the exceedance intensity should be calculated
468467
locally (at each centroid). Defaults to (25, 50, 100, 250).
469468
method : str
470-
Method to interpolate to new return periods. Currently available are "interpolate" and
471-
"stepfunction". Defauls to "interpolate".
472-
intensity_cutoff : float, optional
473-
Minimal threshold to filter the hazard intensity. If set to None, self.intensity_thres
469+
Method to interpolate to new return periods. Currently available are "interpolate",
470+
"extrapolate" and "stepfunction". If set to "interpolate" or "stepfunction", return
471+
periods larger than the Hazard object's observed local return periods will be assigned
472+
the largest local intensity, and return periods smaller than the Hazard object's
473+
observed local return periods will be assigned 0. If set to "extrapolate", local
474+
exceedance intensities will be extrapolated (and interpolated).
475+
Defauls to "interpolate".
476+
min_intensity : float, optional
477+
Minimum threshold to filter the hazard intensity. If set to None, self.intensity_thres
474478
will be used. Defaults to None.
475479
log_frequency : bool, optional
476480
This parameter is only used if method is set to "interpolate". If set to True,
@@ -480,12 +484,6 @@ def local_exceedance_intensity(
480484
This parameter is only used if method is set to "interpolate". If set to True,
481485
intensity values are converted to log scale before inter- and extrapolation.
482486
Defaults to True.
483-
extrapolation : bool, optional
484-
This parameter is only used if method is set to "interpolate". If set to True, local
485-
exceedance intensities will be extrapolated. If set to False, return periods larger than
486-
the Hazard object's observed local return periods will be assigned the largest
487-
local intensity, and return periods smaller than the Impact object's observed local
488-
return periods will be assigned 0. Defaults to True.
489487
490488
Returns
491489
-------
@@ -499,8 +497,8 @@ def local_exceedance_intensity(
499497
column_label : function
500498
Column-label-generating function, for reporting and plotting
501499
"""
502-
if not intensity_cutoff and intensity_cutoff != 0:
503-
intensity_cutoff = self.intensity_thres
500+
if not min_intensity and min_intensity != 0:
501+
min_intensity = self.intensity_thres
504502
#check frequency unit
505503
if self.frequency_unit in ['1/year', 'annual', '1/y', '1/a']:
506504
return_period_unit = 'years'
@@ -528,16 +526,17 @@ def local_exceedance_intensity(
528526

529527
# fit intensities to cummulative frequencies
530528
frequency = np.cumsum(frequency[::-1])[::-1]
531-
if method == 'interpolate':
532-
inten_stats[:,i] = u_interp.interpolate_ev(
533-
1/np.array(return_periods), frequency[::-1], intensity[::-1], logx=log_frequeny,
534-
logy=log_intensity, y_threshold=intensity_cutoff, y_asymptotic=0., extrapolation=extrapolation
535-
)
536-
elif method == 'stepfunction':
529+
if method == 'stepfunction':
537530
inten_stats[:,i] = u_interp.stepfunction_ev(
538-
1/np.array(return_periods), frequency[::-1], intensity[::-1], y_threshold=intensity_cutoff,
531+
1/np.array(return_periods), frequency[::-1], intensity[::-1], y_threshold=min_intensity,
539532
y_asymptotic=0.
540533
)
534+
elif method == 'interpolate' or method == 'extrapolate':
535+
extrapolation = (method == 'extrapolate')
536+
inten_stats[:,i] = u_interp.interpolate_ev(
537+
1/np.array(return_periods), frequency[::-1], intensity[::-1], logx=log_frequeny,
538+
logy=log_intensity, y_threshold=min_intensity, y_asymptotic=0., extrapolation=extrapolation
539+
)
541540
else:
542541
raise ValueError(f"Unknown method: {method}")
543542

@@ -556,8 +555,11 @@ def local_exceedance_intensity(
556555
#TODO: note different calculation in changelog
557556
def local_exceedance_inten(self, return_period=(25, 50, 100, 250)):
558557
"""This function is deprecated, use Hazard.local_exceedance_intensity instead."""
559-
LOGGER.warning("The use of Hazard.local_exceedance_inten is deprecated."
560-
"Use Hazard.local_exceedance_intensity instead.")
558+
LOGGER.warning(
559+
"The use of Hazard.local_exceedance_inten is deprecated. Use "
560+
"Hazard.local_exceedance_intensity instead. Some errors in the previous calculation "
561+
"in Hazard.local_exceedance_inten have been corrected. To reproduce data with the "
562+
"previous calculation, use CLIMADA v5.0.0 or less.")
561563
return self.local_exceedance_intensity(return_period)[0].values[:,1:].T.astype(float)
562564

563565
def sanitize_event_ids(self):
@@ -570,8 +572,7 @@ def local_return_period(
570572
self,
571573
threshold_intensities=(10., 20.),
572574
method='interpolate',
573-
intensity_cutoff = None,
574-
extrapolation=False,
575+
min_intensity = None,
575576
log_frequency=True,
576577
log_intensity=True
577578
):
@@ -585,10 +586,15 @@ def local_return_period(
585586
User-specified hazard intensities for which the return period should be calculated
586587
locally (at each centroid). Defaults to (10, 20)
587588
method : str
588-
Method to interpolate to new intensity values. Currently available are "interpolate" and
589-
"stepfunction". Defauls to "interpolate".
590-
intensity_cutoff : float, optional
591-
Minimal threshold to filter the hazard intensity. If set to None, self.intensity_thres
589+
Method to interpolate to new threshold intensities. Currently available are
590+
"interpolate", "extrapolate" and "stepfunction". If set to "interpolate" or
591+
"stepfunction", threshold intensities larger than the Hazard object's local
592+
intensities will be assigned NaN, and threshold intensities smaller than the Hazard
593+
object's local intensities will be assigned the smallest observed local return period.
594+
If set to "extrapolate", local return periods will be extrapolated (and interpolated).
595+
Defaults to "interpolate".
596+
min_intensity : float, optional
597+
Minimum threshold to filter the hazard intensity. If set to None, self.intensity_thres
592598
will be used. Defaults to None.
593599
log_frequency : bool, optional
594600
This parameter is only used if method is set to "interpolate". If set to True,
@@ -598,12 +604,6 @@ def local_return_period(
598604
This parameter is only used if method is set to "interpolate". If set to True,
599605
intensity values are converted to log scale before inter- and extrapolation.
600606
Defaults to True.
601-
extrapolation : bool, optional
602-
This parameter is only used if method is set to "interpolate". If set to True, local
603-
return periods will be extrapolated. If set to False, threshold intensities larger than
604-
the Hazard object's local intensities will be assigned NaN, and threshold intensities
605-
smaller than the Hazard object's local intensities will be assigned the smallest
606-
observed local return period. Defaults to False.
607607
608608
Returns
609609
-------
@@ -617,8 +617,8 @@ def local_return_period(
617617
column_label : function
618618
Column-label-generating function, for reporting and plotting
619619
"""
620-
if not intensity_cutoff and intensity_cutoff != 0:
621-
intensity_cutoff = self.intensity_thres
620+
if not min_intensity and min_intensity != 0:
621+
min_intensity = self.intensity_thres
622622
#check frequency unit
623623
if self.frequency_unit in ['1/year', 'annual', '1/y', '1/a']:
624624
return_period_unit = 'Years'
@@ -649,14 +649,15 @@ def local_return_period(
649649

650650
# fit intensities to cummulative frequencies
651651
frequency = np.cumsum(frequency[::-1])[::-1]
652-
if method == 'interpolate':
652+
if method == 'stepfunction':
653+
return_periods[:,i] = u_interp.stepfunction_ev(
654+
threshold_intensities, intensity, frequency, x_threshold=min_intensity
655+
)
656+
elif method == 'interpolate' or method == "extrapolate":
657+
extrapolation = (method == "extrapolate")
653658
return_periods[:,i] = u_interp.interpolate_ev(
654659
threshold_intensities, intensity, frequency, logx=log_intensity,
655-
logy=log_frequency, x_threshold=intensity_cutoff, extrapolation=extrapolation, y_asymptotic=np.nan
656-
)
657-
elif method == 'stepfunction':
658-
return_periods[:,i] = u_interp.stepfunction_ev(
659-
threshold_intensities, intensity, frequency, x_threshold=intensity_cutoff
660+
logy=log_frequency, x_threshold=min_intensity, extrapolation=extrapolation, y_asymptotic=np.nan
660661
)
661662
else:
662663
raise ValueError(f"Unknown method: {method}")

climada/hazard/test/test_base.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,7 +1060,7 @@ def test_local_exceedance_intensity(self):
10601060
)
10611061

10621062
def test_local_return_period(self):
1063-
"""Test local return periods easy lin lin interpolation"""
1063+
"""Test local return periods with lin lin interpolation"""
10641064
haz = dummy_hazard()
10651065
haz.intensity = sparse.csr_matrix([
10661066
[1., 4., 1.],
@@ -1072,7 +1072,8 @@ def test_local_return_period(self):
10721072
# second centroid has intensities 2, 4 with cum frequencies 2, 1
10731073
# third centroid has intensities 1 with cum frequencies 1 (0 intensity is neglected)
10741074
# testing at intensities 1, 2, 3
1075-
return_stats, _, _ = haz.local_return_period(threshold_intensities, log_frequency=False, log_intensity=False, intensity_cutoff=0)
1075+
return_stats, _, _ = haz.local_return_period(
1076+
threshold_intensities, log_frequency=False, log_intensity=False, min_intensity=0)
10761077
np.testing.assert_allclose(
10771078
return_stats[return_stats.columns[1:]].values,
10781079
np.array([

climada/test/test_engine.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,8 @@ def test_calc_sensitivity_pass(self):
291291
class TestImpactRPCals(unittest.TestCase):
292292
"""Test the return periods and exceedance impact calculation of Impact objects"""
293293

294-
def test_local_exceedance_impact_options(self):
295-
"""Test local exceedance impacts per return period with different options"""
294+
def test_local_exceedance_impact_methods(self):
295+
"""Test local exceedance impacts per return period with different methods"""
296296
impact = dummy_impact()
297297
impact.coord_exp = np.array([np.arange(4), np.arange(4)]).T
298298
impact.imp_mat = sp.sparse.csr_matrix(
@@ -324,7 +324,7 @@ def test_local_exceedance_impact_options(self):
324324

325325
# test log log extrapolation
326326
impact_stats, _, _ = impact.local_exceedance_impact(
327-
return_periods=(1000, 30, .1))
327+
return_periods=(1000, 30, .1), method = "extrapolate")
328328
np.testing.assert_allclose(
329329
impact_stats.values[:,1:].astype(float),
330330
np.array([
@@ -337,7 +337,7 @@ def test_local_exceedance_impact_options(self):
337337

338338
# test log log interpolation and no extrapolation
339339
impact_stats, _, _ = impact.local_exceedance_impact(
340-
return_periods=(1000, 30, .1), extrapolation=False)
340+
return_periods=(1000, 30, .1))
341341
np.testing.assert_allclose(
342342
impact_stats.values[:,1:].astype(float),
343343
np.array([
@@ -351,7 +351,7 @@ def test_local_exceedance_impact_options(self):
351351
# test lin lin interpolation with no extrapolation
352352
impact_stats, _, _ = impact.local_exceedance_impact(
353353
return_periods=(1000, 30, .1),
354-
log_frequency=False, log_impact=False, extrapolation=False)
354+
log_frequency=False, log_impact=False)
355355
np.testing.assert_allclose(
356356
impact_stats.values[:,1:].astype(float),
357357
np.array([

0 commit comments

Comments
 (0)