From ce2629e0944c1aaffff1647576a9edc1b43d5450 Mon Sep 17 00:00:00 2001 From: Valentin Gebhart Date: Tue, 15 Apr 2025 15:31:32 +0200 Subject: [PATCH 1/3] add option to crop raster plots around centroids --- climada/engine/impact.py | 8 +++++++- climada/hazard/plot.py | 12 +++++++++++- climada/util/plot.py | 18 +++++++++++++++++- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/climada/engine/impact.py b/climada/engine/impact.py index f0b22767e..a6ed4c0de 100644 --- a/climada/engine/impact.py +++ b/climada/engine/impact.py @@ -1178,6 +1178,7 @@ def plot_rp_imp( return_periods=(25, 50, 100, 250), log10_scale=True, axis=None, + mask_rel_distance=None, kwargs_local_exceedance_impact=None, **kwargs, ): @@ -1242,7 +1243,12 @@ def plot_rp_imp( ) axis = u_plot.plot_from_gdf( - impacts_stats, title, column_labels, axis=axis, **kwargs + impacts_stats, + title, + column_labels, + axis=axis, + mask_rel_distance=mask_rel_distance, + **kwargs, ) return axis, impacts_stats_vals diff --git a/climada/hazard/plot.py b/climada/hazard/plot.py index 0af866c7b..aa48296da 100644 --- a/climada/hazard/plot.py +++ b/climada/hazard/plot.py @@ -40,6 +40,7 @@ def plot_rp_intensity( self, return_periods=(25, 50, 100, 250), axis=None, + mask_rel_distance=None, kwargs_local_exceedance_intensity=None, **kwargs, ): @@ -89,7 +90,12 @@ def plot_rp_intensity( ) axis = u_plot.plot_from_gdf( - inten_stats, title, column_labels, axis=axis, **kwargs + inten_stats, + title, + column_labels, + axis=axis, + mask_rel_distance=mask_rel_distance, + **kwargs, ) return axis, inten_stats.values[:, 1:].T.astype(float) @@ -100,6 +106,7 @@ def plot_intensity( smooth=True, axis=None, adapt_fontsize=True, + mask_rel_distance=None, **kwargs, ): """Plot intensity values for a selected event or centroid. @@ -148,6 +155,7 @@ def plot_intensity( crs_epsg, axis, adapt_fontsize=adapt_fontsize, + mask_rel_distance=mask_rel_distance, **kwargs, ) if centr is not None: @@ -215,6 +223,7 @@ def _event_plot( axis=None, figsize=(9, 13), adapt_fontsize=True, + mask_rel_distance=None, **kwargs, ): """Plot an event of the input matrix. @@ -283,6 +292,7 @@ def _event_plot( figsize=figsize, proj=crs_espg, adapt_fontsize=adapt_fontsize, + mask_rel_distance=mask_rel_distance, **kwargs, ) diff --git a/climada/util/plot.py b/climada/util/plot.py index d23ed42e5..97ea79b66 100644 --- a/climada/util/plot.py +++ b/climada/util/plot.py @@ -47,6 +47,7 @@ from mpl_toolkits.axes_grid1 import make_axes_locatable from rasterio.crs import CRS from scipy.interpolate import griddata +from scipy.spatial import cKDTree from shapely.geometry import box import climada.util.coordinates as u_coord @@ -337,6 +338,7 @@ def geo_im_from_array( axes=None, figsize=(9, 13), adapt_fontsize=True, + mask_rel_distance=None, **kwargs, ): """Image(s) plot defined in array(s) over input coordinates. @@ -448,6 +450,18 @@ def geo_im_from_array( (grid_x, grid_y), fill_value=min_value, ) + # Compute distance of each grid point to the nearest known point + if mask_rel_distance is not None: + tree = cKDTree(np.array((coord[:, 1], coord[:, 0])).T) + distances, _ = tree.query( + np.c_[grid_x.ravel(), grid_y.ravel()], + p=2, # for plotting squares and not sphere around centroids use p=np.inf + ) + threshold = ( + max(extent[1] - extent[0], extent[3] - extent[2]) + * mask_rel_distance + ) + grid_im[(distances.reshape(grid_im.shape) > threshold)] = min_value else: grid_x = coord[:, 1].reshape((width, height)).transpose() grid_y = coord[:, 0].reshape((width, height)).transpose() @@ -477,7 +491,7 @@ def geo_im_from_array( ) # handle NaNs in griddata color_nan = "gainsboro" - if np.any(np.isnan(x) for x in grid_im): + if np.isnan(grid_im).any(): no_data_patch = mpatches.Patch( facecolor=color_nan, edgecolor="black", label="NaN" ) @@ -1086,6 +1100,7 @@ def plot_from_gdf( axis=None, figsize=(9, 13), adapt_fontsize=True, + mask_rel_distance=None, **kwargs, ): """Plot several subplots from different columns of a GeoDataFrame, e.g., for @@ -1168,6 +1183,7 @@ def plot_from_gdf( axes=axis, figsize=figsize, adapt_fontsize=adapt_fontsize, + mask_rel_distance=mask_rel_distance, **kwargs, ) From 45537e74473fda318ed17b24e4641e9d720fc43e Mon Sep 17 00:00:00 2001 From: Valentin Gebhart Date: Tue, 15 Apr 2025 15:52:31 +0200 Subject: [PATCH 2/3] update docstrings --- climada/engine/impact.py | 5 +++++ climada/hazard/plot.py | 38 ++++++++++++++++++++++++++++++++++++-- climada/util/plot.py | 10 ++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/climada/engine/impact.py b/climada/engine/impact.py index a6ed4c0de..57361d090 100644 --- a/climada/engine/impact.py +++ b/climada/engine/impact.py @@ -1195,6 +1195,11 @@ def plot_rp_imp( plot impact as log10(impact). Default: True smooth : bool, optional smooth plot to plot.RESOLUTIONxplot.RESOLUTION. Default: True + mask_rel_distance: float, optional + Relative distance (with respect to maximal map extent in longitude or latitude) to data + points above which plot should not display values. For instance, to only plot values + at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + Default is None. kwargs_local_exceedance_impact: dict Dictionary of keyword arguments for the method impact.local_exceedance_impact. kwargs : dict, optional diff --git a/climada/hazard/plot.py b/climada/hazard/plot.py index aa48296da..613ce7828 100644 --- a/climada/hazard/plot.py +++ b/climada/hazard/plot.py @@ -57,6 +57,11 @@ def plot_rp_intensity( axis to use kwargs_local_exceedance_intensity: dict Dictionary of keyword arguments for the method hazard.local_exceedance_intensity. + mask_rel_distance: float, optional + Relative distance (with respect to maximal map extent in longitude or latitude) to data + points above which plot should not display values. For instance, to only plot values + at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + Default is None. kwargs: optional arguments for pcolormesh matplotlib function used in event plots @@ -130,6 +135,11 @@ def plot_intensity( in module `climada.util.plot`) axis: matplotlib.axes._subplots.AxesSubplot, optional axis to use + mask_rel_distance: float, optional + Relative distance (with respect to maximal map extent in longitude or latitude) to data + points above which plot should not display values. For instance, to only plot values + at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + Default is None. kwargs: optional arguments for pcolormesh matplotlib function used in event plots or for plot function used in centroids plots @@ -165,7 +175,15 @@ def plot_intensity( raise ValueError("Provide one event id or one centroid id.") - def plot_fraction(self, event=None, centr=None, smooth=True, axis=None, **kwargs): + def plot_fraction( + self, + event=None, + centr=None, + smooth=True, + axis=None, + mask_rel_distance=None, + **kwargs, + ): """Plot fraction values for a selected event or centroid. Parameters @@ -187,6 +205,11 @@ def plot_fraction(self, event=None, centr=None, smooth=True, axis=None, **kwargs in module `climada.util.plot`) axis: matplotlib.axes._subplots.AxesSubplot, optional axis to use + mask_rel_distance: float, optional + Relative distance (with respect to maximal map extent in longitude or latitude) to data + points above which plot should not display values. For instance, to only plot values + at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + Default is None. kwargs: optional arguments for pcolormesh matplotlib function used in event plots or for plot function used in centroids plots @@ -204,7 +227,13 @@ def plot_fraction(self, event=None, centr=None, smooth=True, axis=None, **kwargs if isinstance(event, str): event = self.get_event_id(event) return self._event_plot( - event, self.fraction, col_label, smooth, axis, **kwargs + event, + self.fraction, + col_label, + smooth, + axis, + mask_rel_distance=mask_rel_distance, + **kwargs, ) if centr is not None: if isinstance(centr, tuple): @@ -245,6 +274,11 @@ def _event_plot( axis to use figsize: tuple, optional figure size for plt.subplots + mask_rel_distance: float, optional + Relative distance (with respect to maximal map extent in longitude or latitude) to data + points above which plot should not display values. For instance, to only plot values + at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + Default is None. kwargs: optional arguments for pcolormesh matplotlib function diff --git a/climada/util/plot.py b/climada/util/plot.py index 97ea79b66..b7e675e3b 100644 --- a/climada/util/plot.py +++ b/climada/util/plot.py @@ -370,6 +370,11 @@ def geo_im_from_array( adapt_fontsize : bool, optional If set to true, the size of the fonts will be adapted to the size of the figure. Otherwise the default matplotlib font size is used. Default is True. + mask_rel_distance: float, optional + Relative distance (with respect to maximal map extent in longitude or latitude) to data + points above which plot should not display values. For instance, to only plot values + at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + Default is None. **kwargs arbitrary keyword arguments for pcolormesh matplotlib function @@ -1123,6 +1128,11 @@ def plot_from_gdf( adapt_fontsize: bool, optional If set to true, the size of the fonts will be adapted to the size of the figure. Otherwise the default matplotlib font size is used. Default is True. + mask_rel_distance: float, optional + Relative distance (with respect to maximal map extent in longitude or latitude) to data + points above which plot should not display values. For instance, to only plot values + at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + Default is None. kwargs: optional Arguments for pcolormesh matplotlib function used in event plots. From 7635890b4f9690eaa8988bf470ce46805fb93d90 Mon Sep 17 00:00:00 2001 From: Valentin Gebhart Date: Wed, 14 May 2025 19:49:47 +0200 Subject: [PATCH 3/3] change name of keyword parameter --- climada/engine/impact.py | 8 ++++---- climada/hazard/plot.py | 32 ++++++++++++++++---------------- climada/util/plot.py | 18 +++++++++--------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/climada/engine/impact.py b/climada/engine/impact.py index 57361d090..408a9ccb2 100644 --- a/climada/engine/impact.py +++ b/climada/engine/impact.py @@ -1178,7 +1178,7 @@ def plot_rp_imp( return_periods=(25, 50, 100, 250), log10_scale=True, axis=None, - mask_rel_distance=None, + mask_relative_distance=None, kwargs_local_exceedance_impact=None, **kwargs, ): @@ -1195,10 +1195,10 @@ def plot_rp_imp( plot impact as log10(impact). Default: True smooth : bool, optional smooth plot to plot.RESOLUTIONxplot.RESOLUTION. Default: True - mask_rel_distance: float, optional + mask_relative_distance: float, optional Relative distance (with respect to maximal map extent in longitude or latitude) to data points above which plot should not display values. For instance, to only plot values - at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + at the centroids, use mask_relative_distance=0.01. If None, the plot is not masked. Default is None. kwargs_local_exceedance_impact: dict Dictionary of keyword arguments for the method impact.local_exceedance_impact. @@ -1252,7 +1252,7 @@ def plot_rp_imp( title, column_labels, axis=axis, - mask_rel_distance=mask_rel_distance, + mask_relative_distance=mask_relative_distance, **kwargs, ) return axis, impacts_stats_vals diff --git a/climada/hazard/plot.py b/climada/hazard/plot.py index 613ce7828..1e108c7d9 100644 --- a/climada/hazard/plot.py +++ b/climada/hazard/plot.py @@ -40,7 +40,7 @@ def plot_rp_intensity( self, return_periods=(25, 50, 100, 250), axis=None, - mask_rel_distance=None, + mask_relative_distance=None, kwargs_local_exceedance_intensity=None, **kwargs, ): @@ -57,10 +57,10 @@ def plot_rp_intensity( axis to use kwargs_local_exceedance_intensity: dict Dictionary of keyword arguments for the method hazard.local_exceedance_intensity. - mask_rel_distance: float, optional + mask_relative_distance: float, optional Relative distance (with respect to maximal map extent in longitude or latitude) to data points above which plot should not display values. For instance, to only plot values - at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + at the centroids, use mask_relative_distance=0.01. If None, the plot is not masked. Default is None. kwargs: optional arguments for pcolormesh matplotlib function used in event plots @@ -99,7 +99,7 @@ def plot_rp_intensity( title, column_labels, axis=axis, - mask_rel_distance=mask_rel_distance, + mask_relative_distance=mask_relative_distance, **kwargs, ) return axis, inten_stats.values[:, 1:].T.astype(float) @@ -111,7 +111,7 @@ def plot_intensity( smooth=True, axis=None, adapt_fontsize=True, - mask_rel_distance=None, + mask_relative_distance=None, **kwargs, ): """Plot intensity values for a selected event or centroid. @@ -135,10 +135,10 @@ def plot_intensity( in module `climada.util.plot`) axis: matplotlib.axes._subplots.AxesSubplot, optional axis to use - mask_rel_distance: float, optional + mask_relative_distance: float, optional Relative distance (with respect to maximal map extent in longitude or latitude) to data points above which plot should not display values. For instance, to only plot values - at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + at the centroids, use mask_relative_distance=0.01. If None, the plot is not masked. Default is None. kwargs: optional arguments for pcolormesh matplotlib function @@ -165,7 +165,7 @@ def plot_intensity( crs_epsg, axis, adapt_fontsize=adapt_fontsize, - mask_rel_distance=mask_rel_distance, + mask_relative_distance=mask_relative_distance, **kwargs, ) if centr is not None: @@ -181,7 +181,7 @@ def plot_fraction( centr=None, smooth=True, axis=None, - mask_rel_distance=None, + mask_relative_distance=None, **kwargs, ): """Plot fraction values for a selected event or centroid. @@ -205,10 +205,10 @@ def plot_fraction( in module `climada.util.plot`) axis: matplotlib.axes._subplots.AxesSubplot, optional axis to use - mask_rel_distance: float, optional + mask_relative_distance: float, optional Relative distance (with respect to maximal map extent in longitude or latitude) to data points above which plot should not display values. For instance, to only plot values - at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + at the centroids, use mask_relative_distance=0.01. If None, the plot is not masked. Default is None. kwargs: optional arguments for pcolormesh matplotlib function @@ -232,7 +232,7 @@ def plot_fraction( col_label, smooth, axis, - mask_rel_distance=mask_rel_distance, + mask_relative_distance=mask_relative_distance, **kwargs, ) if centr is not None: @@ -252,7 +252,7 @@ def _event_plot( axis=None, figsize=(9, 13), adapt_fontsize=True, - mask_rel_distance=None, + mask_relative_distance=None, **kwargs, ): """Plot an event of the input matrix. @@ -274,10 +274,10 @@ def _event_plot( axis to use figsize: tuple, optional figure size for plt.subplots - mask_rel_distance: float, optional + mask_relative_distance: float, optional Relative distance (with respect to maximal map extent in longitude or latitude) to data points above which plot should not display values. For instance, to only plot values - at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + at the centroids, use mask_relative_distance=0.01. If None, the plot is not masked. Default is None. kwargs: optional arguments for pcolormesh matplotlib function @@ -326,7 +326,7 @@ def _event_plot( figsize=figsize, proj=crs_espg, adapt_fontsize=adapt_fontsize, - mask_rel_distance=mask_rel_distance, + mask_relative_distance=mask_relative_distance, **kwargs, ) diff --git a/climada/util/plot.py b/climada/util/plot.py index b7e675e3b..f43e88fd5 100644 --- a/climada/util/plot.py +++ b/climada/util/plot.py @@ -338,7 +338,7 @@ def geo_im_from_array( axes=None, figsize=(9, 13), adapt_fontsize=True, - mask_rel_distance=None, + mask_relative_distance=None, **kwargs, ): """Image(s) plot defined in array(s) over input coordinates. @@ -370,10 +370,10 @@ def geo_im_from_array( adapt_fontsize : bool, optional If set to true, the size of the fonts will be adapted to the size of the figure. Otherwise the default matplotlib font size is used. Default is True. - mask_rel_distance: float, optional + mask_relative_distance: float, optional Relative distance (with respect to maximal map extent in longitude or latitude) to data points above which plot should not display values. For instance, to only plot values - at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + at the centroids, use mask_relative_distance=0.01. If None, the plot is not masked. Default is None. **kwargs arbitrary keyword arguments for pcolormesh matplotlib function @@ -456,7 +456,7 @@ def geo_im_from_array( fill_value=min_value, ) # Compute distance of each grid point to the nearest known point - if mask_rel_distance is not None: + if mask_relative_distance is not None: tree = cKDTree(np.array((coord[:, 1], coord[:, 0])).T) distances, _ = tree.query( np.c_[grid_x.ravel(), grid_y.ravel()], @@ -464,7 +464,7 @@ def geo_im_from_array( ) threshold = ( max(extent[1] - extent[0], extent[3] - extent[2]) - * mask_rel_distance + * mask_relative_distance ) grid_im[(distances.reshape(grid_im.shape) > threshold)] = min_value else: @@ -1105,7 +1105,7 @@ def plot_from_gdf( axis=None, figsize=(9, 13), adapt_fontsize=True, - mask_rel_distance=None, + mask_relative_distance=None, **kwargs, ): """Plot several subplots from different columns of a GeoDataFrame, e.g., for @@ -1128,10 +1128,10 @@ def plot_from_gdf( adapt_fontsize: bool, optional If set to true, the size of the fonts will be adapted to the size of the figure. Otherwise the default matplotlib font size is used. Default is True. - mask_rel_distance: float, optional + mask_relative_distance: float, optional Relative distance (with respect to maximal map extent in longitude or latitude) to data points above which plot should not display values. For instance, to only plot values - at the centroids, use mask_rel_distance=0.01. If None, the plot is not masked. + at the centroids, use mask_relative_distance=0.01. If None, the plot is not masked. Default is None. kwargs: optional Arguments for pcolormesh matplotlib function used in event plots. @@ -1193,7 +1193,7 @@ def plot_from_gdf( axes=axis, figsize=figsize, adapt_fontsize=adapt_fontsize, - mask_rel_distance=mask_rel_distance, + mask_relative_distance=mask_relative_distance, **kwargs, )