diff --git a/climada/engine/impact.py b/climada/engine/impact.py index f0b22767e..57361d090 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, ): @@ -1194,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 @@ -1242,7 +1248,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..613ce7828 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, ): @@ -56,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 @@ -89,7 +95,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 +111,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. @@ -123,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 @@ -148,6 +165,7 @@ def plot_intensity( crs_epsg, axis, adapt_fontsize=adapt_fontsize, + mask_rel_distance=mask_rel_distance, **kwargs, ) if centr is not None: @@ -157,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 @@ -179,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 @@ -196,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): @@ -215,6 +252,7 @@ def _event_plot( axis=None, figsize=(9, 13), adapt_fontsize=True, + mask_rel_distance=None, **kwargs, ): """Plot an event of the input matrix. @@ -236,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 @@ -283,6 +326,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..b7e675e3b 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. @@ -368,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 @@ -448,6 +455,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 +496,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 +1105,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 @@ -1108,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. @@ -1168,6 +1193,7 @@ def plot_from_gdf( axes=axis, figsize=figsize, adapt_fontsize=adapt_fontsize, + mask_rel_distance=mask_rel_distance, **kwargs, )