Skip to content

Commit 498b16c

Browse files
Merge remote-tracking branch 'origin/develop' into feature/zenodo_attributes
2 parents 725d17a + 0c462e8 commit 498b16c

32 files changed

+582
-190
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
# Do not abort other tests if only a single one fails
2323
fail-fast: false
2424
matrix:
25-
python-version: ["3.9", "3.10", "3.11"]
25+
python-version: ["3.10", "3.11"]
2626

2727
steps:
2828
-

.readthedocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ build:
1111
# Append fixed Python version to requirements
1212
jobs:
1313
pre_create_environment:
14-
- echo " - python=3.9" >> requirements/env_climada.yml
14+
- echo " - python=3.11" >> requirements/env_climada.yml
1515

1616
conda:
1717
environment: requirements/env_climada.yml

CHANGELOG.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,41 @@ Code freeze date: YYYY-MM-DD
1010

1111
### Dependency Changes
1212

13+
Added:
14+
15+
- `osm-flex` >=1.1
16+
17+
Updated:
18+
19+
- `cartopy` >=0.23 → >=0.24
20+
- `cfgrib` >=0.9.9,<0.9.10 &rarr; >=0.9
21+
- `dask` >=2024.2,<2024.3 &rarr; >=2025.2
22+
- `eccodes` >=2.27,<2.28 &rarr; >=2.40
23+
- `gdal` >=3.6 &rarr; >=3.10
24+
- `geopandas` >=0.14 &rarr; >=0.14,<1.0
25+
- `h5py` >=3.8 &rarr; >=3.12
26+
- `haversine` >=2.8 &rarr; >=2.9
27+
- `matplotlib-base` >=3.9 &rarr; >=3.10
28+
- `netcdf4` >=1.6 &rarr; >=1.7
29+
- `numba` >=0.60 &rarr; >=0.61
30+
- `pillow` =9.4 &rarr; =11.1
31+
- `pyproj` >=3.5 &rarr; >=3.7
32+
- `pytables` >=3.7 &rarr; >=3.10
33+
- `python` =3.9 &rarr; =3.11
34+
- `rasterio` >=1.3 &rarr; >=1.4
35+
- `scikit-learn` >=1.5 &rarr; >=1.6
36+
- `scipy` >=1.13 &rarr; >=1.14,<1.15
37+
- `tqdm` >=4.66 &rarr; >=4.67
38+
- `xarray` >=2024.6 &rarr; >=2025.1
39+
- `xlsxwriter` >=3.1 &rarr; >=3.2
40+
41+
Removed:
42+
43+
- `pyepsg`
44+
1345
### Added
1446

47+
- `climada.hazard.tc_tracks.TCTracks.from_FAST` function, add Australia basin (AU) [#993](https://github.com/CLIMADA-project/climada_python/pull/993)
1548
- Add `osm-flex` package to CLIMADA core [#981](https://github.com/CLIMADA-project/climada_python/pull/981)
1649
- `doc.tutorial.climada_entity_Exposures_osm.ipynb` tutorial explaining how to use `osm-flex`with CLIMADA
1750
- `climada.util.coordinates.bounding_box_global` function [#980](https://github.com/CLIMADA-project/climada_python/pull/980)
@@ -39,6 +72,8 @@ Code freeze date: YYYY-MM-DD
3972
- In `climada.util.plot.geo_im_from_array`, NaNs are plotted in gray while cells with no centroid are not plotted [#929](https://github.com/CLIMADA-project/climada_python/pull/929)
4073
- Renamed `climada.util.plot.subplots_from_gdf` to `climada.util.plot.plot_from_gdf` [#929](https://github.com/CLIMADA-project/climada_python/pull/929)
4174
- `Hazard.local_exceedance_inten`, `Hazard.local_return_period`, and `Impact.local_exceedance_imp` call the corresponding new functions and a deprecation warning is added [#918](https://github.com/CLIMADA-project/climada_python/pull/918). Some inconsistencies in the previous versions are removed and the default method is changed. To reconstruct results from the previous versions, use CLIMADA v5.0.0 or less.
75+
- elements of `event_name` are now explicitly converted to `str` in `from_raster`, `from_xarray_raster`, `from_excel` and `from_csv`. [#951](https://github.com/CLIMADA-project/climada_python/pull/951), [#910](https://github.com/CLIMADA-project/climada_python/issues/910)
76+
- `event_id` and `event_name` are now explicitly converted to respectively a `np.ndarray` (`event_id`), a `list` (`event_name`) in readers. [#951](https://github.com/CLIMADA-project/climada_python/pull/951), [#950](https://github.com/CLIMADA-project/climada_python/issues/950)
4277
- Exposures complete overhaul. Notably
4378
- the _geometry_ column of the inherent `GeoDataFrame` is set up at initialization
4479
- latitude and longitude column are no longer present there (the according arrays can be retrieved as properties of the Exposures object: `exp.latitude` instead of `exp.gdf.latitude.values`).
@@ -56,6 +91,7 @@ Code freeze date: YYYY-MM-DD
5691

5792
### Deprecated
5893

94+
- `climada.hazard.trop_cyclone.trop_cyclone_windfields.compute_angular_windspeeds.cyclostrophic` argument
5995
- `climada.entity.exposures.Exposures.meta` attribute
6096
- `climada.entity.exposures.Exposures.set_lat_lon` method
6197
- `climada.entity.exposures.Exposures.set_geometry_points` method

README.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
# CLIMADA
66

7-
[CLIMADA](https://climada.ethz.ch/climada/) stands for **CLIM**ate **ADA**ptation and is a probabilistic natural catastrophe impact model, that also calculates averted damage (benefit) thanks to adaptation measures of any kind (from grey to green infrastructure, behavioural, etc.).
7+
[CLIMADA](https://climada.ethz.ch/climada/) (CLIMate ADAptation) is a free and open-source software framework for climate risk assessment and adaptation
8+
option appraisal. Designed by a large scientific community, it helps reasearchers, policymakers, and businesses analyse the impacts of natural hazards and
9+
explore adaptation strategies.
810

911
As of today, CLIMADA provides global coverage of major climate-related extreme-weather hazards at high resolution (4x4km) via a [data API](https://climada.ethz.ch/data-api/v1/docs) For select hazards, historic and probabilistic events sets, for past, present and future climate exist at distinct time horizons.
1012
You will find a repository containing scientific peer-reviewed articles that explain software components implemented in CLIMADA [here](https://github.com/CLIMADA-project/climada_papers).
@@ -37,18 +39,17 @@ Follow the [tutorials](https://climada-python.readthedocs.io/en/stable/tutorial/
3739

3840
The online documentation is available on [Read the Docs](https://climada-python.readthedocs.io/en/stable/).The documentation of each release version of CLIMADA can be accessed separately through the drop-down menu at the bottom of the left sidebar. Additionally, the version 'stable' refers to the most recent release (installed via `conda`), and 'latest' refers to the latest unstable development version (the `develop` branch).
3941

40-
4142
CLIMADA python:
4243

43-
* [online (recommended)](https://climada-python.readthedocs.io/en/latest/)
44-
* [PDF file](https://climada-python.readthedocs.io/_/downloads/en/stable/pdf/)
45-
* [core Tutorials on GitHub](https://github.com/CLIMADA-project/climada_python/tree/main/doc/tutorial)
44+
- [online (recommended)](https://climada-python.readthedocs.io/en/latest/)
45+
- [PDF file](https://climada-python.readthedocs.io/_/downloads/en/stable/pdf/)
46+
- [core Tutorials on GitHub](https://github.com/CLIMADA-project/climada_python/tree/main/doc/tutorial)
4647

4748
CLIMADA petals:
4849

49-
* [online (recommended)](https://climada-petals.readthedocs.io/en/latest/)
50-
* [PDF file](https://climada-petals.readthedocs.io/_/downloads/en/stable/pdf/)
51-
* [petals Tutorials on GitHub](https://github.com/CLIMADA-project/climada_petals/tree/main/doc/tutorial)
50+
- [online (recommended)](https://climada-petals.readthedocs.io/en/latest/)
51+
- [PDF file](https://climada-petals.readthedocs.io/_/downloads/en/stable/pdf/)
52+
- [petals Tutorials on GitHub](https://github.com/CLIMADA-project/climada_petals/tree/main/doc/tutorial)
5253

5354
The documentation can also be [built locally](https://climada-python.readthedocs.io/en/latest/README.html).
5455

@@ -74,6 +75,6 @@ We use [SemVer](http://semver.org/) for versioning. For the versions available,
7475

7576
Copyright (C) 2017 ETH Zurich, CLIMADA contributors listed in AUTHORS.
7677

77-
CLIMADA is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3, 29 June 2007 as published by the Free Software Foundation, https://www.gnu.org/licenses/gpl-3.0.html
78+
CLIMADA is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3, 29 June 2007 as published by the Free Software Foundation, <https://www.gnu.org/licenses/gpl-3.0.html>
7879

79-
CLIMADA is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: https://www.gnu.org/licenses/gpl-3.0.html
80+
CLIMADA is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <https://www.gnu.org/licenses/gpl-3.0.html>

climada/engine/impact.py

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import pandas as pd
4242
import xlsxwriter
4343
from deprecation import deprecated
44+
from pandas.api.types import is_string_dtype
4445
from pyproj import CRS as pyprojCRS
4546
from rasterio.crs import CRS as rasterioCRS # pylint: disable=no-name-in-module
4647
from scipy import sparse
@@ -50,7 +51,6 @@
5051
import climada.util.dates_times as u_dt
5152
import climada.util.interpolation as u_interp
5253
import climada.util.plot as u_plot
53-
from climada import CONFIG
5454
from climada.entity import Exposures
5555
from climada.util.constants import CMAP_IMPACT, DEF_CRS, DEF_FREQ_UNIT
5656
from climada.util.select import get_attributes_with_matching_dimension
@@ -107,8 +107,8 @@ def __init__(
107107
crs=DEF_CRS,
108108
eai_exp=None,
109109
at_event=None,
110-
tot_value=0.,
111-
aai_agg=0.,
110+
tot_value=0.0,
111+
aai_agg=0.0,
112112
unit="",
113113
imp_mat=None,
114114
haz_type="",
@@ -216,8 +216,8 @@ def calc(
216216
"The use of Impact().calc() is deprecated."
217217
" Use ImpactCalc().impact() instead."
218218
)
219-
from climada.engine.impact_calc import (
220-
ImpactCalc, # pylint: disable=import-outside-toplevel
219+
from climada.engine.impact_calc import ( # pylint: disable=import-outside-toplevel
220+
ImpactCalc,
221221
)
222222

223223
impcalc = ImpactCalc(exposures, impact_funcs, hazard)
@@ -1191,6 +1191,8 @@ def write_csv(self, file_name):
11911191
file_name : str
11921192
absolute path of the file
11931193
"""
1194+
if not all((isinstance(val, str) for val in self.event_name)):
1195+
raise TypeError("'event_name' must be a list of strings")
11941196
LOGGER.info("Writing %s", file_name)
11951197
with open(file_name, "w", encoding="utf-8") as imp_file:
11961198
imp_wr = csv.writer(imp_file)
@@ -1239,6 +1241,8 @@ def write_excel(self, file_name):
12391241
file_name : str
12401242
absolute path of the file
12411243
"""
1244+
if not all((isinstance(val, str) for val in self.event_name)):
1245+
raise TypeError("'event_name' must be a list of strings")
12421246
LOGGER.info("Writing %s", file_name)
12431247

12441248
def write_col(i_col, imp_ws, xls_data):
@@ -1453,7 +1457,13 @@ def from_csv(cls, file_name):
14531457
imp.aai_agg = imp_df["aai_agg"][0]
14541458
imp.event_id = imp_df["event_id"][~np.isnan(imp_df["event_id"])].values
14551459
num_ev = imp.event_id.size
1456-
imp.event_name = imp_df["event_name"][:num_ev].values.tolist()
1460+
event_names = imp_df["event_name"][:num_ev]
1461+
if not is_string_dtype(event_names):
1462+
warnings.warn(
1463+
"Some event names are not str will be converted to str.", UserWarning
1464+
)
1465+
event_names = event_names.astype(str)
1466+
imp.event_name = event_names.values.tolist()
14571467
imp.date = imp_df["event_date"][:num_ev].values
14581468
imp.at_event = imp_df["at_event"][:num_ev].values
14591469
imp.frequency = imp_df["event_frequency"][:num_ev].values
@@ -1475,7 +1485,7 @@ def from_csv(cls, file_name):
14751485
def read_csv(self, *args, **kwargs):
14761486
"""This function is deprecated, use Impact.from_csv instead."""
14771487
LOGGER.warning(
1478-
"The use of Impact.read_csv is deprecated." "Use Impact.from_csv instead."
1488+
"The use of Impact.read_csv is deprecated. Use Impact.from_csv instead."
14791489
)
14801490
self.__dict__ = Impact.from_csv(*args, **kwargs).__dict__
14811491

@@ -1494,28 +1504,32 @@ def from_excel(cls, file_name):
14941504
Impact from excel file
14951505
"""
14961506
LOGGER.info("Reading %s", file_name)
1497-
dfr = pd.read_excel(file_name)
1498-
imp = cls(haz_type=str(dfr["haz_type"][0]))
1499-
1500-
imp.unit = dfr["unit"][0]
1501-
imp.tot_value = dfr["tot_value"][0]
1502-
imp.aai_agg = dfr["aai_agg"][0]
1507+
imp_df = pd.read_excel(file_name)
1508+
imp = cls(haz_type=str(imp_df["haz_type"][0]))
15031509

1504-
imp.event_id = dfr["event_id"][~np.isnan(dfr["event_id"].values)].values
1505-
imp.event_name = dfr["event_name"][: imp.event_id.size].values
1506-
imp.date = dfr["event_date"][: imp.event_id.size].values
1507-
imp.frequency = dfr["event_frequency"][: imp.event_id.size].values
1510+
imp.unit = imp_df["unit"][0]
1511+
imp.tot_value = imp_df["tot_value"][0]
1512+
imp.aai_agg = imp_df["aai_agg"][0]
1513+
imp.event_id = imp_df["event_id"][~np.isnan(imp_df["event_id"].values)].values
1514+
event_names = imp_df["event_name"][~np.isnan(imp_df["event_id"].values)]
1515+
if not is_string_dtype(event_names):
1516+
warnings.warn(
1517+
"Some event names are not str will be converted to str", UserWarning
1518+
)
1519+
event_names = event_names.astype(str)
1520+
imp.event_name = event_names.values
1521+
imp.date = imp_df["event_date"][: imp.event_id.size].values
1522+
imp.frequency = imp_df["event_frequency"][: imp.event_id.size].values
15081523
imp.frequency_unit = (
1509-
dfr["frequency_unit"][0] if "frequency_unit" in dfr else DEF_FREQ_UNIT
1524+
imp_df["frequency_unit"][0] if "frequency_unit" in imp_df else DEF_FREQ_UNIT
15101525
)
1511-
imp.at_event = dfr["at_event"][: imp.event_id.size].values
1512-
1513-
imp.eai_exp = dfr["eai_exp"][~np.isnan(dfr["eai_exp"].values)].values
1526+
imp.at_event = imp_df["at_event"][: imp.event_id.size].values
1527+
imp.eai_exp = imp_df["eai_exp"][~np.isnan(imp_df["eai_exp"].values)].values
15141528
imp.coord_exp = np.zeros((imp.eai_exp.size, 2))
1515-
imp.coord_exp[:, 0] = dfr["exp_lat"].values[: imp.eai_exp.size]
1516-
imp.coord_exp[:, 1] = dfr["exp_lon"].values[: imp.eai_exp.size]
1529+
imp.coord_exp[:, 0] = imp_df["exp_lat"].values[: imp.eai_exp.size]
1530+
imp.coord_exp[:, 1] = imp_df["exp_lon"].values[: imp.eai_exp.size]
15171531
try:
1518-
imp.crs = u_coord.to_csr_user_input(dfr["exp_crs"].values[0])
1532+
imp.crs = u_coord.to_csr_user_input(imp_df["exp_crs"].values[0])
15191533
except AttributeError:
15201534
imp.crs = DEF_CRS
15211535

@@ -1679,8 +1693,8 @@ def video_direct_impact(
16791693
-------
16801694
list of Impact
16811695
"""
1682-
from climada.engine.impact_calc import (
1683-
ImpactCalc, # pylint: disable=import-outside-toplevel
1696+
from climada.engine.impact_calc import ( # pylint: disable=import-outside-toplevel
1697+
ImpactCalc,
16841698
)
16851699

16861700
if args_exp is None:

climada/engine/test/test_impact.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def test_from_eih_pass(self):
106106
self.assertEqual(imp.frequency_unit, HAZ.frequency_unit)
107107
self.assertEqual(imp.tot_value, tot_value)
108108
np.testing.assert_array_almost_equal(imp.event_id, HAZ.event_id)
109-
np.testing.assert_array_almost_equal(imp.event_name, HAZ.event_name)
109+
np.testing.assert_array_equal(imp.event_name, HAZ.event_name)
110110
np.testing.assert_array_almost_equal(imp.date, HAZ.date)
111111
np.testing.assert_array_almost_equal(imp.frequency, HAZ.frequency)
112112
np.testing.assert_array_almost_equal(imp.eai_exp, fake_eai_exp)

climada/engine/test/test_impact_calc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ def test_empty_impact(self):
297297

298298
def test_single_event_impact(self):
299299
"""Check impact for single event"""
300-
haz = HAZ.select([1])
300+
haz = HAZ.select(event_id=[1])
301301
icalc = ImpactCalc(ENT.exposures, ENT.impact_funcs, haz)
302302
impact = icalc.impact()
303303
aai_agg = 0.0

climada/engine/unsequa/calc_base.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ def make_sample(self, N, sampling_method="saltelli", sampling_kwargs=None):
207207
sampling_method : str, optional
208208
The sampling method as defined in SALib. Possible choices:
209209
'saltelli', 'latin', 'morris', 'dgsm', 'fast_sampler', 'ff', 'finite_diff',
210-
https://salib.readthedocs.io/en/latest/api.html
210+
https://salib.readthedocs.io/en/latest/api.html
211211
The default is 'saltelli'.
212212
sampling_kwargs : kwargs, optional
213213
Optional keyword arguments passed on to the SALib sampling_method.
@@ -228,7 +228,6 @@ def make_sample(self, N, sampling_method="saltelli", sampling_kwargs=None):
228228
requirement. Please refer to https://salib.readthedocs.io/en/latest/api.html
229229
for more details.
230230
231-
232231
See Also
233232
--------
234233
SALib.sample: sampling methods from SALib SALib.sample

climada/engine/unsequa/calc_cost_benefit.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ class CalcCostBenefit(Calc):
7777
_metric_names : tuple(str)
7878
Names of the cost benefit output metrics
7979
('tot_climate_risk', 'benefit', 'cost_ben_ratio',
80-
'imp_meas_present', 'imp_meas_future')
81-
80+
'imp_meas_present', 'imp_meas_future')
8281
"""
8382

8483
_input_var_names = (

climada/engine/unsequa/calc_delta_climate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class CalcDeltaImpact(Calc):
8181
_input_var_names : tuple(str)
8282
Names of the required uncertainty input variables
8383
('exp_initial_input_var', 'impf_initial_input_var', 'haz_initial_input_var',
84-
'exp_final_input_var', 'impf_final_input_var', 'haz_final_input_var'')
84+
'exp_final_input_var', 'impf_final_input_var', 'haz_final_input_var'')
8585
_metric_names : tuple(str)
8686
Names of the impact output metrics
8787
('aai_agg', 'freq_curve', 'at_event', 'eai_exp')

0 commit comments

Comments
 (0)