Skip to content

Commit 463367e

Browse files
change to decimals in binning
1 parent f858c0a commit 463367e

File tree

4 files changed

+56
-71
lines changed

4 files changed

+56
-71
lines changed

climada/engine/impact.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ def local_exceedance_impact(
498498
min_impact=0,
499499
log_frequency=True,
500500
log_impact=True,
501-
n_sig_dig=3,
501+
bin_decimals=None,
502502
):
503503
"""Compute local exceedance impact for given return periods. The default method
504504
is fitting the ordered impacts per centroid to the corresponding cummulated
@@ -607,7 +607,7 @@ def local_exceedance_impact(
607607
value_threshold=min_impact,
608608
method=method,
609609
y_asymptotic=0.0,
610-
n_sig_dig=n_sig_dig,
610+
bin_decimals=bin_decimals,
611611
)
612612
for i_centroid in nonzero_centroids
613613
]
@@ -622,9 +622,11 @@ def local_exceedance_impact(
622622
gdf[col_names] = exceedance_impact
623623
# create label and column_label
624624
label = f"Impact ({self.unit})"
625-
column_label = lambda column_names: [
626-
f"Return Period: {col} {return_period_unit}" for col in column_names
627-
]
625+
626+
def column_label(column_names):
627+
return [
628+
f"Return Period: {col} {return_period_unit}" for col in column_names
629+
]
628630

629631
return gdf, label, column_label
630632

@@ -650,7 +652,7 @@ def local_return_period(
650652
min_impact=0,
651653
log_frequency=True,
652654
log_impact=True,
653-
n_sig_dig=3,
655+
bin_decimals=None,
654656
):
655657
"""Compute local return periods for given threshold impacts. The default method
656658
is fitting the ordered impacts per centroid to the corresponding cummulated
@@ -754,7 +756,7 @@ def local_return_period(
754756
value_threshold=min_impact,
755757
method=method,
756758
y_asymptotic=np.nan,
757-
n_sig_dig=n_sig_dig,
759+
bin_decimals=bin_decimals,
758760
)
759761
for i_centroid in nonzero_centroids
760762
]
@@ -771,9 +773,11 @@ def local_return_period(
771773

772774
# create label and column_label
773775
label = f"Return Periods ({return_period_unit})"
774-
column_label = lambda column_names: [
775-
f"Impact: {col} {self.unit}" for col in column_names
776-
]
776+
777+
def column_label(column_names):
778+
return [
779+
f"Return Period: {col} {return_period_unit}" for col in column_names
780+
]
777781

778782
return gdf, label, column_label
779783

@@ -1207,8 +1211,8 @@ def plot_rp_imp(
12071211
"""
12081212

12091213
LOGGER.info(
1210-
"Some errors in the previous calculation of local exceedance impacts have been corrected,"
1211-
" see Impact.local_exceedance_impact. To reproduce data with the "
1214+
"Some errors in the previous calculation of local exceedance impacts have been "
1215+
"corrected, see Impact.local_exceedance_impact. To reproduce data with the "
12121216
"previous calculation, use CLIMADA v5.0.0 or less."
12131217
)
12141218

climada/hazard/base.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ def local_exceedance_intensity(
491491
min_intensity=None,
492492
log_frequency=True,
493493
log_intensity=True,
494-
n_sig_dig=3,
494+
bin_decimals=None,
495495
):
496496
"""Compute local exceedance intensity for given return periods. The default method
497497
is fitting the ordered intensitites per centroid to the corresponding cummulated
@@ -594,7 +594,7 @@ def local_exceedance_intensity(
594594
value_threshold=min_intensity,
595595
method=method,
596596
y_asymptotic=0.0,
597-
n_sig_dig=n_sig_dig,
597+
bin_decimals=bin_decimals,
598598
)
599599
for i_centroid in nonzero_centroids
600600
]
@@ -609,9 +609,11 @@ def local_exceedance_intensity(
609609

610610
# create label and column_label
611611
label = f"Intensity ({self.units})"
612-
column_label = lambda column_names: [
613-
f"Return Period: {col} {return_period_unit}" for col in column_names
614-
]
612+
613+
def column_label(column_names):
614+
return [
615+
f"Return Period: {col} {return_period_unit}" for col in column_names
616+
]
615617

616618
return gdf, label, column_label
617619

@@ -642,7 +644,7 @@ def local_return_period(
642644
min_intensity=None,
643645
log_frequency=True,
644646
log_intensity=True,
645-
n_sig_dig=3,
647+
bin_decimals=None,
646648
):
647649
"""Compute local return periods for given hazard intensities. The default method
648650
is fitting the ordered intensitites per centroid to the corresponding cummulated
@@ -742,7 +744,7 @@ def local_return_period(
742744
value_threshold=min_intensity,
743745
method=method,
744746
y_asymptotic=np.nan,
745-
n_sig_dig=n_sig_dig,
747+
bin_decimals=bin_decimals,
746748
)
747749
for i_centroid in nonzero_centroids
748750
]
@@ -759,9 +761,11 @@ def local_return_period(
759761

760762
# create label and column_label
761763
label = f"Return Periods ({return_period_unit})"
762-
column_label = lambda column_names: [
763-
f"Threshold Intensity: {col} {self.units}" for col in column_names
764-
]
764+
765+
def column_label(column_names):
766+
return [
767+
f"Return Period: {col} {return_period_unit}" for col in column_names
768+
]
765769

766770
return gdf, label, column_label
767771

climada/util/interpolation.py

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def preprocess_and_interpolate_ev(
3838
value_threshold=None,
3939
method="interpolate",
4040
y_asymptotic=np.nan,
41-
n_sig_dig=3,
41+
bin_decimals=None,
4242
):
4343
"""Function to first preprocess (frequency, values) data by binning the data according to
4444
their value with the given number of significant digits (see Notes), compute the cumulative
@@ -114,7 +114,8 @@ def preprocess_and_interpolate_ev(
114114
frequency = frequency[sorted_idxs]
115115

116116
# group similar values together
117-
frequency, values = _group_frequency(frequency, values, n_sig_dig)
117+
if method == "extrapolate" and isinstance(bin_decimals, int):
118+
frequency, values = _group_frequency(frequency, values, bin_decimals)
118119

119120
# transform frequencies to cummulative frequencies
120121
frequency = np.cumsum(frequency[::-1])[::-1]
@@ -142,25 +143,24 @@ def preprocess_and_interpolate_ev(
142143
)
143144

144145
# if test values are provided
145-
else:
146-
if method == "stepfunction":
147-
return _stepfunction_ev(
148-
test_values,
149-
values,
150-
frequency,
151-
x_threshold=value_threshold,
152-
y_asymptotic=y_asymptotic,
153-
)
154-
extrapolation = None if method == "interpolate" else method
155-
return _interpolate_ev(
146+
if method == "stepfunction":
147+
return _stepfunction_ev(
156148
test_values,
157149
values,
158150
frequency,
159-
logx=log_values,
160-
logy=log_frequency,
161151
x_threshold=value_threshold,
162-
extrapolation=extrapolation,
152+
y_asymptotic=y_asymptotic,
163153
)
154+
extrapolation = None if method == "interpolate" else method
155+
return _interpolate_ev(
156+
test_values,
157+
values,
158+
frequency,
159+
logx=log_values,
160+
logy=log_frequency,
161+
x_threshold=value_threshold,
162+
extrapolation=extrapolation,
163+
)
164164

165165

166166
def _interpolate_ev(
@@ -346,7 +346,7 @@ def _interpolate_small_input(x_test, x_train, y_train, logy, y_asymptotic):
346346
return y_test
347347

348348

349-
def _group_frequency(frequency, value, n_sig_dig):
349+
def _group_frequency(frequency, value, bin_decimals):
350350
"""
351351
Util function to aggregate (add) frequencies for equal values
352352
@@ -370,14 +370,15 @@ def _group_frequency(frequency, value, n_sig_dig):
370370
return ([], [])
371371

372372
# round values and group them
373-
value = round_to_sig_digits(value, n_sig_dig)
373+
value = np.around(value, decimals=bin_decimals)
374374
value_unique, start_indices = np.unique(value, return_index=True)
375375
if value_unique.size != frequency.size:
376376
if not all(sorted(start_indices) == start_indices):
377377
LOGGER.warning(
378378
"After grouping values to significant digits, the value array is not sorted."
379-
"The values are not binned. Please choose a larger value of n_sig_dig=%s.",
380-
n_sig_dig,
379+
"The values are not binned. This might be due to floating point error while "
380+
"binning. Please choose a larger value of bin_decimals=%s.",
381+
bin_decimals,
381382
)
382383
return frequency, value
383384

@@ -387,24 +388,3 @@ def _group_frequency(frequency, value, n_sig_dig):
387388
return frequency, value_unique
388389

389390
return frequency, value
390-
391-
392-
def round_to_sig_digits(values, n_sig_dig):
393-
"""round each element array to a number of significant digits
394-
395-
Parameters
396-
----------
397-
values : array-like
398-
values to be rounded
399-
n_sig_dig : int
400-
number of significant digits.
401-
402-
Returns
403-
-------
404-
np.array
405-
rounded array
406-
"""
407-
408-
return np.vectorize(np.format_float_positional)(
409-
values, precision=n_sig_dig, unique=False, fractional=False, trim="k"
410-
).astype(float)

climada/util/test/test_interpolation.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -223,18 +223,15 @@ def test_frequency_group(self):
223223
frequency = np.ones(6)
224224
intensity = np.array([1.00001, 0.9998, 1.0, 2.0, 3.0, 3])
225225
np.testing.assert_allclose(
226-
u_interp._group_frequency(frequency, intensity, n_sig_dig=3),
227-
([3, 1, 2], [1, 2, 3]),
226+
u_interp._group_frequency(frequency, intensity),
227+
(frequency, intensity),
228228
)
229229
np.testing.assert_allclose(
230-
u_interp._group_frequency([], [], n_sig_dig=3), ([], [])
230+
u_interp._group_frequency(frequency, intensity, bin_decimals=3),
231+
([3, 1, 2], [1, 2, 3]),
231232
)
232-
233-
def test_round_to_sig_digits(self):
234-
array = [0.00111, 999.0, 55.5, 0.0, -1.001, -1.08]
235233
np.testing.assert_allclose(
236-
u_interp.round_to_sig_digits(array, n_sig_dig=2),
237-
[0.0011, 1000.0, 56, 0.0, -1.0, -1.1],
234+
u_interp._group_frequency([], [], bin_decimals=3), ([], [])
238235
)
239236

240237
def test_preprocess_and_interpolate_ev(self):

0 commit comments

Comments
 (0)