diff --git a/CHANGELOG.md b/CHANGELOG.md index 78b87a850..ee3376aeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,7 @@ Removed: - Tests with long runtime were moved to integration tests in `climada/test` [#709](https://github.com/CLIMADA-project/climada_python/pull/709) - Use `myst-nb` for parsing Jupyter Notebooks for the documentation instead of `nbsphinx` [#712](https://github.com/CLIMADA-project/climada_python/pull/712) - Installation guide now recommends installing CLIMADA directly via `conda install` [#714](https://github.com/CLIMADA-project/climada_python/pull/714) -- `Exposures.affected_total_value` now takes a hazard intensity threshold as argument. Affected values are only those for which at least one event exceeds the threshold. (previously, all exposures points with an assigned centroid were considered affected) [#702](https://github.com/CLIMADA-project/climada_python/pull/702) +- `Exposures.affected_total_value` now takes a hazard intensity threshold as argument. Affected values are only those for which at least one event exceeds the threshold. (previously, all exposures points with an assigned centroid were considered affected). By default the centroids are reassigned. [#702](https://github.com/CLIMADA-project/climada_python/pull/702) [#730](https://github.com/CLIMADA-project/climada_python/pull/730) - Add option to pass region ID to `LitPop.from_shape` [#720](https://github.com/CLIMADA-project/climada_python/pull/720) - Slightly improved performance on `LitPop`-internal computations [#720](https://github.com/CLIMADA-project/climada_python/pull/720) diff --git a/climada/entity/exposures/base.py b/climada/entity/exposures/base.py index 54ef1f557..02250a9b2 100644 --- a/climada/entity/exposures/base.py +++ b/climada/entity/exposures/base.py @@ -1048,7 +1048,12 @@ def centroids_total_value(self, hazard): ) return np.sum(self.gdf.value.values[nz_mask]) - def affected_total_value(self, hazard: Hazard, threshold_affected: float = 0): + def affected_total_value( + self, + hazard: Hazard, + threshold_affected: float = 0, + overwrite_assigned_centroids: bool = True, + ): """ Total value of the exposures that are affected by at least one hazard event (sum of value of all exposures points for which @@ -1061,6 +1066,11 @@ def affected_total_value(self, hazard: Hazard, threshold_affected: float = 0): threshold_affected : int or float Hazard intensity threshold above which an exposures is considere affected. + The default is 0. + overwrite_assigned_centroids : boolean + Assign centroids from the hazard to the exposures and overwrite + existing ones. + The default is True. Returns ------- @@ -1069,7 +1079,17 @@ def affected_total_value(self, hazard: Hazard, threshold_affected: float = 0): a centroids is assigned and that have at least one event intensity above threshold. + See Also + -------- + Exposures.assign_centroids : method to assign centroids. + + Note + ---- + The fraction attribute of the hazard is ignored. Thus, for hazards + with fraction defined the affected values will be overestimated. + """ + self.assign_centroids(hazard=hazard, overwrite=overwrite_assigned_centroids) assigned_centroids = self.gdf[hazard.centr_exp_col] nz_mask = (self.gdf.value.values > 0) & (assigned_centroids.values >= 0) cents = np.unique(assigned_centroids[nz_mask]) diff --git a/climada/entity/exposures/test/test_base.py b/climada/entity/exposures/test/test_base.py index 3e13e3de7..9fa2fdd18 100644 --- a/climada/entity/exposures/test/test_base.py +++ b/climada/entity/exposures/test/test_base.py @@ -190,27 +190,50 @@ def test_affected_total_value(self): gdf = gpd.GeoDataFrame( { "value": [1, 2, 3, 4, 5, 6], - "latitude": [1, 2, 3, 4, 5, 6], - "longitude": [-1, -2, -3, -4, -5, -6], + "latitude": [1, 2, 3, 4, 1, 0], + "longitude": [-1, -2, -3, -4, 0, 1], "centr_" + haz_type: [0, 2, 2, 3, -1, 4], } ) exp = Exposures(gdf, crs=4326) intensity = sp.sparse.csr_matrix(np.array([[0, 0, 1, 10, 2], [-1, 0, 0, 1, 2]])) - cent = Centroids(lat=np.array([1, 2, 3, 4]), lon=np.array([1, 2, 3, 4])) + cent = Centroids(lat=np.array([1, 2, 3, 4]), lon=np.array([-1, -2, -3, -4])) haz = Hazard( haz_type=haz_type, centroids=cent, intensity=intensity, event_id=[1, 2] ) - tot_val = exp.affected_total_value(haz, threshold_affected=0) + # do not reassign centroids + tot_val = exp.affected_total_value( + haz, threshold_affected=0, overwrite_assigned_centroids=False + ) self.assertEqual(tot_val, np.sum(exp.gdf.value[[1, 2, 3, 5]])) - tot_val = exp.affected_total_value(haz, threshold_affected=3) + tot_val = exp.affected_total_value( + haz, threshold_affected=3, overwrite_assigned_centroids=False + ) self.assertEqual(tot_val, np.sum(exp.gdf.value[[3]])) - tot_val = exp.affected_total_value(haz, threshold_affected=-2) + tot_val = exp.affected_total_value( + haz, threshold_affected=-2, overwrite_assigned_centroids=False + ) self.assertEqual(tot_val, np.sum(exp.gdf.value[[0, 1, 2, 3, 5]])) - tot_val = exp.affected_total_value(haz, threshold_affected=11) + tot_val = exp.affected_total_value( + haz, threshold_affected=11, overwrite_assigned_centroids=False + ) self.assertEqual(tot_val, 0) + # reassign centroids (i.e. to [0, 1, 2, 3, -1, -1]) + tot_val = exp.affected_total_value( + haz, threshold_affected=11, overwrite_assigned_centroids=True + ) + self.assertEqual(tot_val, 0) + tot_val = exp.affected_total_value( + haz, threshold_affected=0, overwrite_assigned_centroids=False + ) + self.assertEqual(tot_val, 7) + tot_val = exp.affected_total_value( + haz, threshold_affected=3, overwrite_assigned_centroids=False + ) + self.assertEqual(tot_val, 4) + class TestChecker(unittest.TestCase): """Test logs of check function"""