Skip to content

Commit f27790d

Browse files
committed
Merge branch 'develop' into forecast-class
2 parents 4634b30 + a423c78 commit f27790d

50 files changed

Lines changed: 8170 additions & 1328 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 5 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -51,22 +51,11 @@ coverage.xml
5151
.hypothesis/
5252

5353
# Temporary data generated by unit tests
54-
climada/engine/test/data/supplychain/*
55-
climada/engine/test/data/test.csv
56-
climada/engine/test/data/test_imp_mat.npz
57-
climada/engine/test/data/test.xlsx
58-
climada/entity/impact_funcs/test/data/test_write.xlsx
59-
climada/hazard/test/data/tc_tracks_nc/*
60-
climada/hazard/test/data/tc_tracks.h5
61-
climada/hazard/test/data/test_centr.h5
62-
climada/hazard/test/data/test_haz.h5
63-
climada/hazard/test/data/test_unsupported.h5
64-
climada/test/data/1988234N13299.nc
65-
climada/test/data/exposure_buildings_default_47_7.h5
66-
climada/test/data/exposure_high_47_8.h5
67-
climada/test/data/test_write_hazard.tif
68-
climada/util/test/data/save_test.pkl
69-
climada/util/test/data/test_write_raster.tif
54+
climada/engine/test/data/
55+
climada/entity/impact_funcs/test/data/
56+
climada/hazard/test/data/
57+
climada/test/data/
58+
climada/util/test/data/
7059

7160
# Translations
7261
*.mo
@@ -128,51 +117,6 @@ venv.bak/
128117
# mac finder files
129118
.DS_Store
130119

131-
# climada system data files
132-
# they get downloaded separately from the repo
133-
data/system/global_coast*
134-
data/system/global_country*
135-
data/system/tmp_elevation.tif
136-
137-
# climada system data files: Nightlight and population data
138-
data/system/BlackMarble*tif
139-
data/system/*stable_lights*.*
140-
data/system/gpw_v4_population_count_rev11_2015_30_sec.tif
141-
142-
# climada system data files: IBTrACS data
143-
data/system/IBTrACS.ALL.v04r00.nc
144-
data/system/data_master_sl_short/
145-
146-
# climada system data files: SPEI data
147-
data/system/spei06.nc
148-
149-
# climada system data files: World Bank data
150-
data/system/OGHIST.xls
151-
data/system/Wealth-Accounts_CSV/
152-
153-
# climada system data files: Credit Suisse Research institute data:
154-
data/system/GDP2Asset_factors_CRI_2016
155-
156-
# climada system data files: SPAM data
157-
data/system/cell5m_allockey_xy.csv
158-
data/system/LicenseV*.pdf
159-
data/system/readme_global_v3r2.txt
160-
data/system/spam*csv
161-
162-
# climada system data files: GPW data
163-
data/system/gpw-v*
164-
data/system/gpw_v*.tif
165-
166-
# climada system data files: NASA distance to coast
167-
data/system/GMT_intermediate_coast*
168-
169-
# climada system data files: folders for hazard and exposure data
170-
data/system/hazard/
171-
data/system/litpop/
172-
data/system/litpop_2014/
173-
174-
# climada data: ISIMIP crop data folder:
175-
data/ISIMIP_crop/
176120

177121
# climada data results folder:
178122
results/
@@ -183,5 +127,3 @@ results/
183127
!.pylintrc
184128
!.readthedocs.yml
185129
!.github
186-
climada_petals/
187-
climada_python/

CHANGELOG.md

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

1515
- Support for ensemble forecast data as hazard via `HazardForecast` and `ImpactForecast`, see `doc.user_guide.climada_engine_ImpactForecast.ipynb` [#1115](https://github.com/CLIMADA-project/climada_python/pull/)
1616
- Better type hints and overloads signatures for ImpactFuncSet [#1250](https://github.com/CLIMADA-project/climada_python/pull/1250)
17+
- Add inter- and extrapolation options to `ImpactFreqCurve` with method `interpolate` [#1252](https://github.com/CLIMADA-project/climada_python/pull/1252)
18+
- Add `trajectory` module to ease the handling of multiple risk assessment at different point in time, and enable interpolation in between. [#1197](https://github.com/CLIMADA-project/climada_python/pull/1197), [#1198](https://github.com/CLIMADA-project/climada_python/pull/1198), [#1199](https://github.com/CLIMADA-project/climada_python/pull/1199), [#1200](https://github.com/CLIMADA-project/climada_python/pull/1197), [#1201](https://github.com/CLIMADA-project/climada_python/pull/1197)
1719

1820
### Changed
1921

2022
- Updated Impact Calculation Tutorial (`doc.climada_engine_Impact.ipynb`) [#1095](https://github.com/CLIMADA-project/climada_python/pull/1095).
23+
- Makes current `measure` module a legacy module, moving it to `_legacy_measure`, to retain compatibility with `CostBenefit` class and various tests. [#1274](https://github.com/CLIMADA-project/climada_python/pull/1274)
2124

2225
### Fixed
2326

2427
- Fixed asset count in impact logging message [#1195](https://github.com/CLIMADA-project/climada_python/pull/1195).
28+
- `Hazard.from_raster_xarray` now returns a sparse matrix instead of a sparse array [#1261](https://github.com/CLIMADA-project/climada_python/pull/1261).
29+
- Fix TCTracks.from_FAST duplicate loading from year loop [#1269](github.com/CLIMADA-project/climada_python/pull/1269)
2530

2631
### Deprecated
32+
- `Impact.calc_freq_curve()` should not be given the parameter `return_per`. Use the parameter `return_periods` in `Impact.calc_freq_curve().interpolate()` instead.
2733

2834
### Removed
2935
- `climada.util.earth_engine.py` Google Earth Engine methods did not facilitate direct use of GEE data in CLIMADA. Code was relocated to [climada-snippets](https://github.com/CLIMADA-project/climada-snippets). [#1109](https://github.com/CLIMADA-project/climada_python/pull/1109)

climada/conf/climada.conf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,6 @@
6969
"cache_dir": "{local_data.system}/.apicache",
7070
"supported_hazard_types": ["river_flood", "tropical_cyclone", "storm_europe", "relative_cropyield", "wildfire", "earthquake", "flood", "hail", "aqueduct_coastal_flood"],
7171
"supported_exposures_types": ["litpop", "crop_production", "ssp_population", "crops"]
72-
}
72+
},
73+
"trajectory_caching": true
7374
}

climada/engine/impact.py

Lines changed: 100 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -575,15 +575,6 @@ def local_exceedance_impact(
575575
self.frequency_unit
576576
)
577577

578-
# check method
579-
if method not in [
580-
"interpolate",
581-
"extrapolate",
582-
"extrapolate_constant",
583-
"stepfunction",
584-
]:
585-
raise ValueError(f"Unknown method: {method}")
586-
587578
# calculate local exceedance impact
588579
test_frequency = 1 / np.array(return_periods)
589580

@@ -731,15 +722,6 @@ def local_return_period(
731722
self.frequency_unit
732723
)
733724

734-
# check method
735-
if method not in [
736-
"interpolate",
737-
"extrapolate",
738-
"extrapolate_constant",
739-
"stepfunction",
740-
]:
741-
raise ValueError(f"Unknown method: {method}")
742-
743725
return_periods = np.full((self.imp_mat.shape[1], len(threshold_impact)), np.nan)
744726

745727
nonzero_centroids = np.where(self.imp_mat.getnnz(axis=0) > 0)[0]
@@ -803,6 +785,12 @@ def calc_freq_curve(self, return_per=None):
803785
ifc_impact = self.at_event[sort_idxs][::-1]
804786

805787
if return_per is not None:
788+
warnings.warn(
789+
"Calculating the frequency curve on user-specified return periods is deprecated. "
790+
"Use ImpactFreqCurve.calc_freq_curve().interpolate() instead.",
791+
DeprecationWarning,
792+
stacklevel=2,
793+
)
806794
interp_imp = np.interp(return_per, ifc_return_per, ifc_impact)
807795
ifc_return_per = return_per
808796
ifc_impact = interp_imp
@@ -2321,15 +2309,108 @@ def plot(self, axis=None, log_frequency=False, **kwargs):
23212309
-------
23222310
matplotlib.axes.Axes
23232311
"""
2312+
# check frequency unit
2313+
return_period_unit = u_dt.convert_frequency_unit_to_time_unit(
2314+
self.frequency_unit
2315+
)
2316+
23242317
if not axis:
23252318
_, axis = plt.subplots(1, 1)
23262319
axis.set_title(self.label)
23272320
axis.set_ylabel("Impact (" + self.unit + ")")
2321+
23282322
if log_frequency:
23292323
axis.set_xlabel(f"Exceedance frequency ({self.frequency_unit})")
23302324
axis.set_xscale("log")
23312325
axis.plot(self.return_per**-1, self.impact, **kwargs)
2326+
23322327
else:
2333-
axis.set_xlabel("Return period (year)")
2328+
axis.set_xlabel(f"Return period ({return_period_unit})")
23342329
axis.plot(self.return_per, self.impact, **kwargs)
2330+
23352331
return axis
2332+
2333+
def interpolate(
2334+
self,
2335+
return_periods,
2336+
*,
2337+
method="interpolate",
2338+
log_frequency=True,
2339+
log_impact=True,
2340+
min_impact=0,
2341+
bin_decimals=None,
2342+
y_asymptotic=0.0,
2343+
):
2344+
"""Interpolate and extrapolate impact frequency curve using different methods.
2345+
2346+
Parameters
2347+
----------
2348+
return_periods : Iterable[float]
2349+
return periods for which to evaluate the impact frequency curve
2350+
2351+
method : str, optional
2352+
Method to interpolate to new return periods. Currently available are "interpolate",
2353+
"extrapolate", "extrapolate_constant" and "stepfunction". If set to "interpolate",
2354+
return periods outside the range of the Impact object's observed return periods
2355+
will be assigned NaN. If set to "extrapolate_constant" or "stepfunction",
2356+
return periods larger than the Impact object's observed return periods will be
2357+
assigned the largest impact, and return periods smaller than the Impact object's
2358+
observed return periods will be assigned 0. If set to "extrapolate",
2359+
exceedance impacts will be extrapolated (and interpolated). The extrapolation to
2360+
large return periods uses the two highest impacts of the centroid and their return
2361+
periods and extends the interpolation between these points to the given return period
2362+
(similar for small return periods). Defauls to "interpolate".
2363+
min_impact : float, optional
2364+
Minimum threshold to filter the impact. Defaults to 0.
2365+
log_frequency : bool, optional
2366+
If set to True, (cummulative) frequency values are converted to log scale before
2367+
inter- and extrapolation. Defaults to True.
2368+
log_impact : bool, optional
2369+
If set to True, impact values are converted to log scale before
2370+
inter- and extrapolation. Defaults to True.
2371+
bin_decimals : int, optional
2372+
Number of decimals to group and bin impact values. Binning results in smoother (and
2373+
coarser) interpolation and more stable extrapolation. For more details and sensible
2374+
values for bin_decimals, see Notes. If None, values are not binned. Defaults to None.
2375+
y_asymptotic : float, optional
2376+
Has no effect if method is "interpolate". Else, if data size < 2 or if method
2377+
is set to "extrapolate_constant" or "stepfunction", it provides return value for
2378+
exceeded impact for return periods smaller than the data range. Defaults to 0.
2379+
2380+
Returns
2381+
-------
2382+
ImpactFreqCurve
2383+
impact frequency curve with inter- and extrapolated values
2384+
2385+
See Also
2386+
--------
2387+
util.interpolation.preprocess_and_interpolate_ev :
2388+
inter- and extrapolation method
2389+
"""
2390+
exceedance_frequency = 1 / np.array(return_periods)
2391+
2392+
# sort return periods of ImpactFreqCurve
2393+
sorted_idxs = np.argsort(self.return_per)
2394+
impacts = np.squeeze(np.array(self.impact)[sorted_idxs])
2395+
rps = np.asarray(self.return_per)[sorted_idxs]
2396+
frequency = np.diff(1 / np.array(rps)[::-1], prepend=0)[::-1]
2397+
impact_interpolated = u_interp.preprocess_and_interpolate_ev(
2398+
exceedance_frequency,
2399+
None,
2400+
frequency,
2401+
impacts,
2402+
log_frequency=log_frequency,
2403+
log_values=log_impact,
2404+
value_threshold=min_impact,
2405+
method=method,
2406+
y_asymptotic=y_asymptotic,
2407+
bin_decimals=bin_decimals,
2408+
)
2409+
2410+
return ImpactFreqCurve(
2411+
return_per=return_periods,
2412+
impact=impact_interpolated,
2413+
unit=self.unit,
2414+
frequency_unit=self.frequency_unit,
2415+
label=self.label,
2416+
)

climada/engine/test/test_cost_benefit.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@
3333
risk_rp_100,
3434
risk_rp_250,
3535
)
36+
from climada.entity._legacy_measures import Measure
37+
from climada.entity._legacy_measures.base import LOGGER as ILOG
3638
from climada.entity.disc_rates import DiscRates
3739
from climada.entity.entity_def import Entity
38-
from climada.entity.measures import Measure
39-
from climada.entity.measures.base import LOGGER as ILOG
4040
from climada.hazard.base import Hazard
4141
from climada.test import get_test_file
4242
from climada.util.api_client import Client

climada/engine/test/test_impact.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,61 @@ def test_ref_value_rp_pass(self):
325325
self.assertEqual("USD", ifc.unit)
326326
self.assertEqual("1/week", ifc.frequency_unit)
327327

328+
def test_interpolate_freq_curve(self):
329+
"""Test inter- and extrapolate method of freq curve"""
330+
imp = Impact()
331+
imp.frequency = np.array([0.2, 0.1, 0.1, 0.1])
332+
imp.at_event = np.array([0.0, 100.0, 50.0, 110.0])
333+
imp.unit = "USD"
334+
imp.frequency_unit = "1/year"
335+
336+
ifc = imp.calc_freq_curve()
337+
# the ifc has values
338+
# impacts [0, 50, 100, 110]
339+
# exceedance frequencies [.5, .3, .2, .1]
340+
# return periods [2, 3.3, 5, 10]
341+
342+
# stepfunction assigns zero return periods below data and max(impact) for those above
343+
npt.assert_array_almost_equal(
344+
ifc.interpolate([1, 5, 20], method="stepfunction").impact,
345+
[0.0, 100.0, 110.0],
346+
)
347+
348+
# interpolate assigns nan to return periods outside of data
349+
npt.assert_array_almost_equal(
350+
ifc.interpolate([1, 5, 20], method="interpolate").impact,
351+
[np.nan, 100.0, np.nan],
352+
)
353+
354+
# extrapolate_constant assigns zero return periods below data and max(impact) for those above
355+
npt.assert_array_almost_equal(
356+
ifc.interpolate([1, 5, 20], method="extrapolate_constant").impact,
357+
[0.0, 100.0, 110.0],
358+
)
359+
360+
# by binning the last two digits, 100 and 110 are rounded to 100
361+
npt.assert_array_almost_equal(
362+
ifc.interpolate(
363+
[1, 5, 20], method="extrapolate_constant", bin_decimals=-2
364+
).impact,
365+
[0.0, 100.0, 100.0],
366+
)
367+
368+
# extrapolation is done by neglecting 0 impacts (min_impact=0)
369+
# rp=1: extrapolate impacts [50, 100] and ex_freqs [.3, .2] to ex_freq=1 --> 0
370+
# rp=2.5: extrapolate impacts [50, 100] and ex_freqs [.3, .2] to ex_freq=0.4 --> 0
371+
# rp=4: extrapolate impacts [50, 100] and ex_freqs [.3, .2] to ex_freq=0.25 --> 75
372+
# rp=1: extrapolate impacts [100, 110] and ex_freqs [.2, .1] to ex_freq=0.05 --> 115
373+
npt.assert_array_almost_equal(
374+
ifc.interpolate(
375+
[1.0, 2.5, 4, 20],
376+
method="extrapolate",
377+
log_frequency=False,
378+
log_impact=False,
379+
).impact,
380+
[-300.0, 0.0, 75.0, 115.0],
381+
)
382+
328383

329384
class TestImpactPerYear(unittest.TestCase):
330385
"""Test calc_impact_year_set method"""

climada/engine/unsequa/input_var.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ def ent(
518518
exp_list : [climada.entity.exposures.base.Exposure]
519519
The list of base exposure. Can be one or many to uniformly sample
520520
from.
521-
meas_set : climada.entity.measures.measure_set.MeasureSet
521+
meas_set : climada.entity._legacy_measures.measure_set.MeasureSet
522522
The base measures.
523523
haz_id_dict : dict
524524
Dictionary of the impact functions affected by uncertainty.
@@ -660,7 +660,7 @@ def entfut(
660660
exp_list : [climada.entity.exposures.base.Exposure]
661661
The list of base exposure. Can be one or many to uniformly sample
662662
from.
663-
meas_set : climada.entity.measures.measure_set.MeasureSet
663+
meas_set : climada.entity._legacy_measures.measure_set.MeasureSet
664664
The base measures.
665665
haz_id_dict : dict
666666
Dictionary of the impact functions affected by uncertainty.

climada/entity/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
init entity
2020
"""
2121

22+
from ._legacy_measures import *
2223
from .disc_rates import *
2324
from .entity_def import *
2425
from .exposures import *
2526
from .impact_funcs import *
26-
from .measures import *
File renamed without changes.

0 commit comments

Comments
 (0)