Skip to content

Commit 72ccfc9

Browse files
committed
Merge branch 'develop' into cross-calibrate-impact-functions
2 parents 1d9f508 + 46c4852 commit 72ccfc9

File tree

73 files changed

+6058
-4264
lines changed

Some content is hidden

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

73 files changed

+6058
-4264
lines changed

.github/workflows/ci.yml

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ on: [push]
66
# Use bash explicitly for being able to enter the conda environment
77
defaults:
88
run:
9-
shell: bash -l {0}
9+
shell: bash -el {0}
1010

1111
jobs:
1212
build-and-test:
13-
name: Build Env, Install, Unit Tests
13+
name: 'Core / Unit Test Pipeline'
1414
runs-on: ubuntu-latest
1515
permissions:
1616
# For publishing results
@@ -41,8 +41,6 @@ jobs:
4141
create-args: >-
4242
python=${{ matrix.python-version }}
4343
make
44-
init-shell: >-
45-
bash
4644
# Persist environment for branch, Python version, single day
4745
cache-environment-key: env-${{ github.ref }}-${{ matrix.python-version }}-${{ steps.date.outputs.date }}
4846
-
@@ -59,12 +57,22 @@ jobs:
5957
if: always()
6058
with:
6159
junit_files: tests_xml/tests.xml
62-
check_name: "Unit Test Results Python ${{ matrix.python-version }}"
60+
check_name: "Core / Unit Test Results (${{ matrix.python-version }})"
6361
comment_mode: "off"
6462
-
6563
name: Upload Coverage Reports
6664
if: always()
6765
uses: actions/upload-artifact@v4
6866
with:
69-
name: coverage-report-unittests-py${{ matrix.python-version }}
67+
name: coverage-report-core-unittests-py${{ matrix.python-version }}
7068
path: coverage/
69+
70+
test-petals:
71+
name: Petals Compatibility
72+
uses: CLIMADA-project/climada_petals/.github/workflows/testing.yml@develop
73+
needs: build-and-test
74+
with:
75+
core_branch: ${{ github.ref }}
76+
petals_branch: develop
77+
permissions:
78+
checks: write

AUTHORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@
3535
* Timo Schmid
3636
* Luca Severino
3737
* Samuel Juhel
38+
* Valentin Gebhart

CHANGELOG.md

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

1111
### Dependency Changes
1212

13+
### Added
14+
15+
### Changed
16+
17+
### Fixed
18+
19+
### Deprecated
20+
21+
### Removed
22+
23+
## 5.0.0
24+
25+
Release date: 2024-07-19
26+
27+
### Dependency Changes
28+
29+
Added:
30+
31+
- `bayesian-optimization`
32+
- `seaborn` >=0.13
33+
34+
Updated:
35+
36+
- `bottleneck` >=1.3 → >=1.4
37+
- `cartopy` >=0.22 → >=0.23
38+
- `contextily` >=1.5 → >=1.6
39+
- `dask` >=2024.1,<2024.3 &rarr; >=2024.2,<2024.3
40+
- `matplotlib-base` >=3.8 &rarr; >=3.9
41+
- `numba` >=0.59 &rarr; >=0.60
42+
- `numexpr` >=2.9 &rarr; >=2.10
43+
- `pint` >=0.23 &rarr; >=0.24
44+
- `pycountry` >=22.3 &rarr; >=24.6
45+
- `requests` >=2.31 &rarr; >=2.32
46+
- `salib` >=1.4 &rarr; >=1.5
47+
- `scikit-learn` >=1.4 &rarr; >=1.5
48+
- `scipy` >=1.12 &rarr; >=1.13
49+
- `xarray` >=2024.2 &rarr; >=2024.6
50+
51+
### Added
52+
53+
- GitHub actions workflow for CLIMADA Petals compatibility tests [#855](https://github.com/CLIMADA-project/climada_python/pull/855)
54+
- `climada.util.calibrate` module for calibrating impact functions [#692](https://github.com/CLIMADA-project/climada_python/pull/692)
55+
1356
### Changed
1457

58+
- Use Geopandas GeoDataFrame.plot() for centroids plotting function [896](https://github.com/CLIMADA-project/climada_python/pull/896)
59+
- Update SALib sensitivity and sampling methods from newest version (SALib 1.4.7) [#828](https://github.com/CLIMADA-project/climada_python/issues/828)
60+
- Allow for computation of relative and absolute delta impacts in `CalcDeltaClimate`
61+
- Remove content tables and make minor improvements (fix typos and readability) in
62+
CLIMADA tutorials. [#872](https://github.com/CLIMADA-project/climada_python/pull/872)
1563
- Centroids complete overhaul. Most function should be backward compatible. Internal data is stored in a geodataframe attribute. Raster are now stored as points, and the meta attribute is removed. Several methds were deprecated or removed. [#787](https://github.com/CLIMADA-project/climada_python/pull/787)
1664
- Improved error messages produced by `ImpactCalc.impact()` in case impact function in the exposures is not found in impf_set [#863](https://github.com/CLIMADA-project/climada_python/pull/863)
65+
- Update the Holland et al. 2010 TC windfield model and introduce `model_kwargs` parameter to adjust model parameters [#846](https://github.com/CLIMADA-project/climada_python/pull/846)
66+
- Changed module structure: `climada.hazard.Hazard` has been split into the modules `base`, `io` and `plot` [#871](https://github.com/CLIMADA-project/climada_python/pull/871)
67+
- Ensure `csr_matrix` stored in `climada.hazard.Hazard` have consistent data format and store no explicit zeros when initializing `ImpactCalc` [#893](https://github.com/CLIMADA-project/climada_python/pull/893)
68+
- `Impact.from_hdf5` now calls `str` on `event_name` data that is not strings, and issue a warning then [#894](https://github.com/CLIMADA-project/climada_python/pull/894)
69+
- `Impact.write_hdf5` now throws an error if `event_name` is does not contain strings exclusively [#894](https://github.com/CLIMADA-project/climada_python/pull/894)
70+
- Split `climada.hazard.trop_cyclone` module into smaller submodules without affecting module usage [#911](https://github.com/CLIMADA-project/climada_python/pull/911)
1771

1872
### Fixed
1973

2074
- Avoid an issue where a Hazard subselection would have a fraction matrix with only zeros as entries by throwing an error [#866](https://github.com/CLIMADA-project/climada_python/pull/866)
75+
- Allow downgrading the Python bugfix version to improve environment compatibility [#900](https://github.com/CLIMADA-project/climada_python/pull/900)
76+
- Fix broken links in `CONTRIBUTING.md` [#900](https://github.com/CLIMADA-project/climada_python/pull/900)
77+
- When writing `TCTracks` to NetCDF, only apply compression to `float` or `int` data types. This fixes a downstream issue, see [climada_petals#135](https://github.com/CLIMADA-project/climada_petals/issues/135) [#911](https://github.com/CLIMADA-project/climada_python/pull/911)
2178

2279
### Added
2380

81+
- Method `Hazard.check_matrices` for bringing the stored CSR matrices into "canonical format" [#893](https://github.com/CLIMADA-project/climada_python/pull/893)
82+
- Generic s-shaped impact function via `ImpactFunc.from_poly_s_shape` [#878](https://github.com/CLIMADA-project/climada_python/pull/878)
2483
- climada.hazard.centroids.centr.Centroids.get_area_pixel
2584
- climada.hazard.centroids.centr.Centroids.get_dist_coast
2685
- climada.hazard.centroids.centr.Centroids.get_elevation
@@ -40,6 +99,7 @@ Code freeze date: YYYY-MM-DD
4099
- climada.hazard.centroids.centr.Centroids.empty_geometry_points
41100
- climada.hazard.centroids.centr.Centroids.set_meta_to_lat_lon
42101
- climada.hazard.centroids.centr.Centroids.set_lat_lon_to_meta
102+
- `scheduler` parameter in `climada.util.coordinates.set_df_geometry_points`, as dask is not used anymore, leaving all calculation to shapely [#912](https://github.com/CLIMADA-project/climada_python/pull/912)
43103

44104
### Removed
45105

@@ -151,6 +211,7 @@ Changed:
151211

152212
- `geopandas` >=0.13 &rarr; >=0.14
153213
- `pandas` >=1.5,<2.0 &rarr; >=2.1
214+
- `salib` >=1.3.0 &rarr; >=1.4.7
154215

155216
Removed:
156217

CONTRIBUTING.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Please contact the [lead developers](https://wcr.ethz.ch/research/climada.html)
2222

2323
## Minimal Steps to Contribute
2424

25-
Before you start, please have a look at our [Developer Guide][devguide].
25+
Before you start, please have a look at our Developer Guide section in the [CLIMADA Docs][docs].
2626

2727
To contribute follow these steps:
2828

@@ -65,21 +65,22 @@ To contribute follow these steps:
6565
6666
## Resources
6767
68-
The CLIMADA documentation provides a [Developer Guide][devguide].
68+
The [CLIMADA documentation][docs] provides several Developer Guides.
6969
Here's a selection of the commonly required information:
7070

7171
* How to use Git and GitHub for CLIMADA development: [Development and Git and CLIMADA](https://climada-python.readthedocs.io/en/latest/guide/Guide_Git_Development.html)
72-
* Coding instructions for CLIMADA: [Python Dos and Don'ts](https://climada-python.readthedocs.io/en/latest/guide/Guide_PythonDos-n-Donts.html), [Performance Tips](https://climada-python.readthedocs.io/en/latest/guide/Guide_Py_Performance.html), [CLIMADA Conventions](https://climada-python.readthedocs.io/en/latest/guide/Guide_Miscellaneous.html)
73-
* How to execute tests in CLIMADA: [Testing and Continuous Integration][testing]
72+
* Coding instructions for CLIMADA: [Python Dos and Don'ts](https://climada-python.readthedocs.io/en/latest/guide/Guide_PythonDos-n-Donts.html), [Performance Tips](https://climada-python.readthedocs.io/en/latest/guide/Guide_Py_Performance.html), [CLIMADA Conventions](https://climada-python.readthedocs.io/en/latest/guide/Guide_CLIMADA_conventions.html)
73+
* How to execute tests in CLIMADA: [Testing][testing] and [Continuous Integration](https://climada-python.readthedocs.io/en/latest/guide/Guide_continuous_integration_GitHub_actions.html)
7474
7575
## Pull Requests
7676
7777
After developing a new feature, fixing a bug, or updating the tutorials, you can create a [pull request](https://docs.github.com/en/pull-requests) to have your changes reviewed and then merged into the CLIMADA code base.
7878
To ensure that your pull request can be reviewed quickly and easily, please have a look at the _Resources_ above before opening a pull request.
79-
In particular, please check out the [Pull Request instructions](https://climada-python.readthedocs.io/en/latest/guide/Guide_Git_Development.html#Pull-requests).
79+
In particular, please check out the [Pull Request instructions](https://climada-python.readthedocs.io/en/latest/guide/Guide_Git_Development.html#pull-requests).
8080
8181
We provide a description template for pull requests that helps you provide the essential information for reviewers.
8282
It also contains a checklist for both pull request authors and reviewers to guide the review process.
8383
84+
[docs]: https://climada-python.readthedocs.io/en/latest/
8485
[devguide]: https://climada-python.readthedocs.io/en/latest/#developer-guide
85-
[testing]: https://climada-python.readthedocs.io/en/latest/guide/Guide_Continuous_Integration_and_Testing.html
86+
[testing]: https://climada-python.readthedocs.io/en/latest/guide/Guide_Testing.html

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
PYTEST_JUNIT_ARGS = --junitxml=tests_xml/tests.xml
66

77
PYTEST_COV_ARGS = \
8-
--cov --cov-config=.coveragerc --cov-report html --cov-report xml \
9-
--cov-report term:skip-covered
8+
--cov --cov-config=.coveragerc --cov-report html:coverage \
9+
--cov-report xml:coverage.xml --cov-report term:skip-covered
1010

1111
PYTEST_ARGS = $(PYTEST_JUNIT_ARGS) $(PYTEST_COV_ARGS)
1212

climada/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '4.1.2-dev'
1+
__version__ = '5.0.1-dev'

climada/conf/climada.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
"cache_db": "{local_data.system}/.downloads.db",
6868
"cache_enabled": true,
6969
"cache_dir": "{local_data.system}/.apicache",
70-
"supported_hazard_types": ["river_flood", "tropical_cyclone", "storm_europe", "relative_cropyield", "wildfire", "earthquake", "flood", "hail"],
70+
"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"]
7272
}
7373
}

climada/engine/impact.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -937,11 +937,6 @@ def write_hdf5(self, file_path: Union[str, Path], dense_imp_mat: bool=False):
937937
938938
The impact matrix can be stored in a sparse or dense format.
939939
940-
Notes
941-
-----
942-
This writer does not support attributes with variable types. Please make sure
943-
that ``event_name`` is a list of equally-typed values, e.g., all ``str``.
944-
945940
Parameters
946941
----------
947942
file_path : str or Path
@@ -950,6 +945,11 @@ def write_hdf5(self, file_path: Union[str, Path], dense_imp_mat: bool=False):
950945
If ``True``, write the impact matrix as dense matrix that can be more easily
951946
interpreted by common H5 file readers but takes up (vastly) more space.
952947
Defaults to ``False``.
948+
949+
Raises
950+
------
951+
TypeError
952+
If :py:attr:`event_name` does not contain strings exclusively.
953953
"""
954954
# Define writers for all types (will be filled later)
955955
type_writers = dict()
@@ -983,7 +983,7 @@ def write(group: h5py.Group, name: str, value: Any):
983983

984984
def _str_type_helper(values: Collection):
985985
"""Return string datatype if we assume 'values' contains strings"""
986-
if isinstance(next(iter(values)), str):
986+
if all((isinstance(val, str) for val in values)):
987987
return h5py.string_dtype()
988988
return None
989989

@@ -1037,6 +1037,8 @@ def write_csr(group, name, value):
10371037
# Now write all attributes
10381038
# NOTE: Remove leading underscore to write '_tot_value' as regular attribute
10391039
for name, value in self.__dict__.items():
1040+
if name == "event_name" and _str_type_helper(value) is None:
1041+
raise TypeError("'event_name' must be a list of strings")
10401042
write(file, name.lstrip("_"), value)
10411043

10421044
def write_sparse_csr(self, file_name):
@@ -1240,10 +1242,18 @@ def from_hdf5(cls, file_path: Union[str, Path]):
12401242
).intersection(file.keys())
12411243
kwargs.update({attr: file[attr][:] for attr in array_attrs})
12421244

1243-
# Special handling for 'event_name' because it's a list of strings
1245+
# Special handling for 'event_name' because it should be a list of strings
12441246
if "event_name" in file:
12451247
# pylint: disable=no-member
1246-
kwargs["event_name"] = list(file["event_name"].asstr()[:])
1248+
try:
1249+
event_name = file["event_name"].asstr()[:]
1250+
except TypeError:
1251+
LOGGER.warning(
1252+
"'event_name' is not stored as strings. Trying to decode "
1253+
"values with 'str()' instead."
1254+
)
1255+
event_name = map(str, file["event_name"][:])
1256+
kwargs["event_name"] = list(event_name)
12471257

12481258
# Create the impact object
12491259
return cls(**kwargs)

climada/engine/impact_calc.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ def __init__(self,
4747
The dimension of the imp_mat variable must be compatible with the
4848
exposures and hazard objects.
4949
50+
This will call :py:meth:`climada.hazard.base.Hazard.check_matrices`.
51+
5052
Parameters
5153
----------
5254
exposures : climada.entity.Exposures
@@ -61,6 +63,8 @@ def __init__(self,
6163
self.exposures = exposures
6264
self.impfset = impfset
6365
self.hazard = hazard
66+
self.hazard.check_matrices()
67+
6468
# exposures index to use for matrix reconstruction
6569
self._orig_exp_idx = np.arange(self.exposures.gdf.shape[0])
6670

climada/engine/test/test_impact.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -779,7 +779,8 @@ def test_select_event_identity_pass(self):
779779
ent.exposures.assign_centroids(hazard)
780780

781781
# Compute the impact over the whole exposures
782-
imp = ImpactCalc(ent.exposures, ent.impact_funcs, hazard).impact(save_mat=True, assign_centroids=False)
782+
imp = ImpactCalc(ent.exposures, ent.impact_funcs, hazard).impact(
783+
save_mat=True, assign_centroids=False)
783784

784785
sel_imp = imp.select(event_ids=imp.event_id,
785786
event_names=imp.event_name,
@@ -1019,10 +1020,11 @@ def test_write_hdf5_without_imp_mat(self):
10191020

10201021
def test_write_hdf5_type_fail(self):
10211022
"""Test that writing attributes with varying types results in an error"""
1022-
self.impact.event_name = [1, "a", 1.0, "b", "c", "d"]
1023-
with self.assertRaises(TypeError) as cm:
1023+
self.impact.event_name = ["a", 1, 1.0, "b", "c", "d"]
1024+
with self.assertRaisesRegex(
1025+
TypeError, "'event_name' must be a list of strings"
1026+
):
10241027
self.impact.write_hdf5(self.filepath)
1025-
self.assertIn("No conversion path for dtype", str(cm.exception))
10261028

10271029
def test_cycle_hdf5(self):
10281030
"""Test writing and reading the same object"""
@@ -1120,6 +1122,15 @@ def test_read_hdf5_full(self):
11201122
impact = Impact.from_hdf5(self.filepath)
11211123
npt.assert_array_equal(impact.imp_mat.toarray(), [[0, 1, 2], [3, 0, 0]])
11221124

1125+
# Check with non-string event_name
1126+
event_name = [1.2, 2]
1127+
with h5py.File(self.filepath, "r+") as file:
1128+
del file["event_name"]
1129+
file.create_dataset("event_name", data=event_name)
1130+
with self.assertLogs("climada.engine.impact", "WARNING") as cm:
1131+
impact = Impact.from_hdf5(self.filepath)
1132+
self.assertIn("'event_name' is not stored as strings", cm.output[0])
1133+
self.assertListEqual(impact.event_name, ["1.2", "2.0"])
11231134

11241135
# Execute Tests
11251136
if __name__ == "__main__":

0 commit comments

Comments
 (0)