Skip to content

Commit 28f8f15

Browse files
exposures-init-geometry (#890)
* wip * climada.entity.Exposures rewrite __init__ * wip * climada.entity.Exposures: refactor __init__ * adaptations to changed Exposures structure: gdf.latitude and gdf.longitude have been eliminated * adaptations to changed Exposures structure: gdf.latitude and gdf.longitude have been eliminated * adaptations to changed Exposures structure: gdf.latitude and gdf.longitude have been eliminated * centroids.Centroids.from_exposures() will always work as geometry column is granted * adaptation to eliminated lat/lon columns * hazard.Centroids: region_id and on_land are not necessarily present in the data frame * Exposures() requires geometry or lat/lon * cangelog * points_to_raster function getting more complicated, considering dataframes with geometry column instead fo lat/lon * pydoc argument description fix * fix typo (bug really) * exposures: remove meta from attributes * introduce exposures properties, region_id etc. consequently use region_id property where applicable * rename and use hazard_impf and hazard_centroids * lint * Exposures: rename pmeta property to _meta * fix changelog * exposures: gracefully handle empty exposures * exposures: linting * Update climada/entity/exposures/base.py Co-authored-by: Samuel Juhel <[email protected]> * petals compatibility test: try and switch the petals branch * fix merging mistake * deprecate set_geomety_points * deprecate set_geomety_points * remove properties and methods from the pydoc attributes section * typo * typo * deprecate set_geomety_points * Exposures.__init__: no need for a temporary geodataframe as u_coord.set_df_geometry_points does not use a scheduler anymore * Exposures.base: amend pydocs * Exposures.base: use get_impf_column in hazard_impf * pydoc Exposures.__init__ * pydoc Exposures.__init__ * changelog updates * deprecate set_geomety_points * jenkins: align with petals * exposures tutorial: listing attributes and properties * exposures: don't do anything in check, update Tutorial * format * import Impact from climada.engine.impact in order to avoid circular imports * avoid circular imports * pre-commit run --all-files * setup: DEPS_TEST update * format all * exposures tutorial: add information about optional columns * clean up tutorials --------- Co-authored-by: Samuel Juhel <[email protected]>
1 parent 48648d9 commit 28f8f15

33 files changed

+1365
-1450
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,6 @@ jobs:
7474
needs: build-and-test
7575
with:
7676
core_branch: ${{ github.ref }}
77-
petals_branch: develop
77+
petals_branch: feature/exposures_crs
7878
permissions:
7979
checks: write

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,26 @@ Code freeze date: YYYY-MM-DD
1313
### Added
1414

1515
- `climada.util.interpolation` module for inter- and extrapolation util functions used in local exceedance intensity and return period functions [#930](https://github.com/CLIMADA-project/climada_python/pull/930)
16+
- `climada.exposures.exposures.Exposures.geometry` property
17+
- `climada.exposures.exposures.Exposures.latitude` property
18+
- `climada.exposures.exposures.Exposures.longitude` property
19+
- `climada.exposures.exposures.Exposures.value` property
20+
- `climada.exposures.exposures.Exposures.region_id` property
21+
- `climada.exposures.exposures.Exposures.category_id` property
22+
- `climada.exposures.exposures.Exposures.cover` property
23+
- `climada.exposures.exposures.Exposures.hazard_impf` method
24+
- `climada.exposures.exposures.Exposures.hazard_centroids` method
1625

1726
### Changed
1827

1928
- Improved scaling factors implemented in `climada.hazard.trop_cyclone.apply_climate_scenario_knu` to model the impact of climate changes to tropical cyclones [#734](https://github.com/CLIMADA-project/climada_python/pull/734)
2029
- 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)
2130
- Renamed `climada.util.plot.subplots_from_gdf` to `climada.util.plot.plot_from_gdf` [#929](https://github.com/CLIMADA-project/climada_python/pull/929)
31+
- Exposures complete overhaul. Notably
32+
- the _geometry_ column of the inherent `GeoDataFrame` is set up at initialization
33+
- 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`).
34+
- `Exposures.gdf` has been renamed to `Exposures.data` (it still works though, as it is a property now pointing to the latter)
35+
- the `check` method does not add a default "IMPF_" column to the GeoDataFrame anymore
2236

2337
### Fixed
2438

@@ -27,6 +41,10 @@ Code freeze date: YYYY-MM-DD
2741

2842
### Deprecated
2943

44+
- `climada.entity.exposures.Exposures.meta` attribute
45+
- `climada.entity.exposures.Exposures.set_lat_lon` method
46+
- `climada.entity.exposures.Exposures.set_geometry_points` method
47+
3048
### Removed
3149

3250
## 5.0.0

climada/engine/forecast.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ def __init__(
187187
if exposure_name is None:
188188
try:
189189
self.exposure_name = u_coord.country_to_iso(
190-
exposure.gdf["region_id"].unique()[0], "name"
190+
np.unique(exposure.region_id)[0], "name"
191191
)
192192
except (KeyError, AttributeError):
193193
self.exposure_name = "custom"

climada/engine/impact.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,7 @@ def from_eih(cls, exposures, hazard, at_event, eai_exp, aai_agg, imp_mat=None):
259259
date=hazard.date,
260260
frequency=hazard.frequency,
261261
frequency_unit=hazard.frequency_unit,
262-
coord_exp=np.stack(
263-
[exposures.gdf["latitude"].values, exposures.gdf["longitude"].values],
264-
axis=1,
265-
),
262+
coord_exp=np.stack([exposures.latitude, exposures.longitude], axis=1),
266263
crs=exposures.crs,
267264
unit=exposures.value_unit,
268265
tot_value=exposures.centroids_total_value(hazard),
@@ -733,9 +730,6 @@ def plot_raster_eai_exposure(
733730
cartopy.mpl.geoaxes.GeoAxesSubplot
734731
"""
735732
eai_exp = self._build_exp()
736-
# we need to set geometry points because the `plot_raster` method accesses the
737-
# exposures' `gdf.crs` property, which raises an error when geometry is not set
738-
eai_exp.set_geometry_points()
739733
axis = eai_exp.plot_raster(
740734
res,
741735
raster_res,

climada/engine/impact_calc.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ def impact(
119119
apply_deductible_to_mat : apply deductible to impact matrix
120120
apply_cover_to_mat : apply cover to impact matrix
121121
"""
122+
# TODO: consider refactoring, making use of Exposures.hazard_impf
122123
# check for compatibility of exposures and hazard type
123124
if all(
124125
name not in self.exposures.gdf.columns

climada/engine/test/test_impact.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,7 @@ def test_from_eih_pass(self):
112112
np.testing.assert_array_almost_equal(imp.eai_exp, fake_eai_exp)
113113
np.testing.assert_array_almost_equal(imp.at_event, fake_at_event)
114114
np.testing.assert_array_almost_equal(
115-
imp.coord_exp,
116-
np.stack([exp.gdf["latitude"].values, exp.gdf["longitude"].values], axis=1),
115+
imp.coord_exp, np.stack([exp.latitude, exp.longitude], axis=1)
117116
)
118117

119118
def test_pyproj_crs(self):
@@ -987,9 +986,9 @@ def test__build_exp(self):
987986

988987
imp = dummy_impact()
989988
exp = imp._build_exp()
990-
np.testing.assert_array_equal(imp.eai_exp, exp.gdf["value"])
991-
np.testing.assert_array_equal(imp.coord_exp[:, 0], exp.gdf["latitude"])
992-
np.testing.assert_array_equal(imp.coord_exp[:, 1], exp.gdf["longitude"])
989+
np.testing.assert_array_equal(imp.eai_exp, exp.value)
990+
np.testing.assert_array_equal(imp.coord_exp[:, 0], exp.latitude)
991+
np.testing.assert_array_equal(imp.coord_exp[:, 1], exp.longitude)
993992
self.assertTrue(u_coord.equal_crs(exp.crs, imp.crs))
994993
self.assertEqual(exp.value_unit, imp.unit)
995994
self.assertEqual(exp.ref_year, 0)
@@ -1000,9 +999,9 @@ def test__exp_build_event(self):
1000999
imp = dummy_impact()
10011000
event_id = imp.event_id[1]
10021001
exp = imp._build_exp_event(event_id=event_id)
1003-
np.testing.assert_array_equal(imp.imp_mat[1].todense().A1, exp.gdf["value"])
1004-
np.testing.assert_array_equal(imp.coord_exp[:, 0], exp.gdf["latitude"])
1005-
np.testing.assert_array_equal(imp.coord_exp[:, 1], exp.gdf["longitude"])
1002+
np.testing.assert_array_equal(imp.imp_mat[1].todense().A1, exp.value)
1003+
np.testing.assert_array_equal(imp.coord_exp[:, 0], exp.latitude)
1004+
np.testing.assert_array_equal(imp.coord_exp[:, 1], exp.longitude)
10061005
self.assertTrue(u_coord.equal_crs(exp.crs, imp.crs))
10071006
self.assertEqual(exp.value_unit, imp.unit)
10081007
self.assertEqual(exp.ref_year, 0)

climada/engine/test/test_impact_calc.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ def check_impact(self, imp, haz, exp, aai_agg, eai_exp, at_event, imp_mat_array=
5050
"""Test properties of imapcts"""
5151
self.assertEqual(len(haz.event_id), len(imp.at_event))
5252
self.assertIsInstance(imp, Impact)
53-
np.testing.assert_allclose(imp.coord_exp[:, 0], exp.gdf["latitude"])
54-
np.testing.assert_allclose(imp.coord_exp[:, 1], exp.gdf["longitude"])
53+
np.testing.assert_allclose(imp.coord_exp[:, 0], exp.latitude)
54+
np.testing.assert_allclose(imp.coord_exp[:, 1], exp.longitude)
5555
self.assertAlmostEqual(imp.aai_agg, aai_agg, 3)
5656
np.testing.assert_allclose(imp.eai_exp, eai_exp, rtol=1e-5)
5757
np.testing.assert_allclose(imp.at_event, at_event, rtol=1e-5)
@@ -490,7 +490,12 @@ def test_minimal_exp_gdf(self):
490490
def test_stitch_impact_matrix(self):
491491
"""Check how sparse matrices from a generator are stitched together"""
492492
icalc = ImpactCalc(
493-
Exposures({"blank": [1, 2, 3, 4]}), ImpactFuncSet(), Hazard()
493+
Exposures(
494+
{"blank": [1, 2, 3, 4]},
495+
geometry=[],
496+
),
497+
ImpactFuncSet(),
498+
Hazard(),
494499
)
495500
icalc.hazard.event_id = np.array([1, 2, 3])
496501
icalc._orig_exp_idx = np.array([0, 1, 2, 3])
@@ -524,7 +529,14 @@ def test_apply_deductible_to_mat(self):
524529

525530
def test_stitch_risk_metrics(self):
526531
"""Test computing risk metrics from an impact matrix generator"""
527-
icalc = ImpactCalc(Exposures({"blank": [1, 2, 3]}), ImpactFuncSet(), Hazard())
532+
icalc = ImpactCalc(
533+
Exposures(
534+
{"blank": [1, 2, 3]},
535+
geometry=[],
536+
),
537+
ImpactFuncSet(),
538+
Hazard(),
539+
)
528540
icalc.hazard.event_id = np.array([1, 2])
529541
icalc.hazard.frequency = np.array([2, 0.5])
530542
icalc._orig_exp_idx = np.array([0, 1, 2])

climada/engine/unsequa/calc_impact.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,9 @@ def uncertainty(
240240

241241
if calc_eai_exp:
242242
exp = self.exp_input_var.evaluate()
243-
coord_df = exp.gdf[["latitude", "longitude"]]
243+
coord_df = pd.DataFrame(
244+
dict(latitude=exp.latitude, longitude=exp.longitude)
245+
)
244246
else:
245247
coord_df = pd.DataFrame([])
246248

0 commit comments

Comments
 (0)