Skip to content

Commit af793bc

Browse files
Add option in raster plot to crop around centroids (#1047)
* add option to crop raster plots around centroids * update docstrings * change name of keyword parameter * change keyword name and improve docstring descriptions * updated changelog * change default value of mask parameter and update changelog
1 parent 1a6df8e commit af793bc

File tree

4 files changed

+87
-6
lines changed

4 files changed

+87
-6
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ Removed:
1515
- `pandas-datareader`
1616

1717
### Added
18-
18+
- Added optional parameter to `geo_im_from_array`, `plot_from_gdf`, `plot_rp_imp`, `plot_rp_intensity`,
19+
`plot_intensity`, `plot_fraction`, `_event_plot` to mask plotting when regions are too far from data points [#1047](https://github.com/CLIMADA-project/climada_python/pull/1047). To recreate previous plots (no masking), the parameter can be set to None.
1920
- Added instructions to install Climada petals on Euler cluster in `doc.guide.Guide_Euler.ipynb` [#1029](https://github.com/CLIMADA-project/climada_python/pull/1029)
2021

2122
### Changed

climada/engine/impact.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,7 @@ def plot_rp_imp(
11781178
return_periods=(25, 50, 100, 250),
11791179
log10_scale=True,
11801180
axis=None,
1181+
mask_distance=0.01,
11811182
kwargs_local_exceedance_impact=None,
11821183
**kwargs,
11831184
):
@@ -1194,6 +1195,11 @@ def plot_rp_imp(
11941195
plot impact as log10(impact). Default: True
11951196
smooth : bool, optional
11961197
smooth plot to plot.RESOLUTIONxplot.RESOLUTION. Default: True
1198+
mask_distance: float, optional
1199+
Only regions are plotted that are closer to any of the data points than this distance,
1200+
relative to overall plot size. For instance, to only plot values
1201+
at the centroids, use mask_distance=0.01. If None, the plot is not masked.
1202+
Default is 0.01.
11971203
kwargs_local_exceedance_impact: dict
11981204
Dictionary of keyword arguments for the method impact.local_exceedance_impact.
11991205
kwargs : dict, optional
@@ -1242,7 +1248,12 @@ def plot_rp_imp(
12421248
)
12431249

12441250
axis = u_plot.plot_from_gdf(
1245-
impacts_stats, title, column_labels, axis=axis, **kwargs
1251+
impacts_stats,
1252+
title,
1253+
column_labels,
1254+
axis=axis,
1255+
mask_distance=mask_distance,
1256+
**kwargs,
12461257
)
12471258
return axis, impacts_stats_vals
12481259

climada/hazard/plot.py

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def plot_rp_intensity(
4040
self,
4141
return_periods=(25, 50, 100, 250),
4242
axis=None,
43+
mask_distance=0.01,
4344
kwargs_local_exceedance_intensity=None,
4445
**kwargs,
4546
):
@@ -56,6 +57,11 @@ def plot_rp_intensity(
5657
axis to use
5758
kwargs_local_exceedance_intensity: dict
5859
Dictionary of keyword arguments for the method hazard.local_exceedance_intensity.
60+
mask_distance: float, optional
61+
Only regions are plotted that are closer to any of the data points than this distance,
62+
relative to overall plot size. For instance, to only plot values
63+
at the centroids, use mask_distance=0.01. If None, the plot is not masked.
64+
Default is 0.01.
5965
kwargs: optional
6066
arguments for pcolormesh matplotlib function used in event plots
6167
@@ -89,7 +95,12 @@ def plot_rp_intensity(
8995
)
9096

9197
axis = u_plot.plot_from_gdf(
92-
inten_stats, title, column_labels, axis=axis, **kwargs
98+
inten_stats,
99+
title,
100+
column_labels,
101+
axis=axis,
102+
mask_distance=mask_distance,
103+
**kwargs,
93104
)
94105
return axis, inten_stats.values[:, 1:].T.astype(float)
95106

@@ -100,6 +111,7 @@ def plot_intensity(
100111
smooth=True,
101112
axis=None,
102113
adapt_fontsize=True,
114+
mask_distance=0.01,
103115
**kwargs,
104116
):
105117
"""Plot intensity values for a selected event or centroid.
@@ -123,6 +135,11 @@ def plot_intensity(
123135
in module `climada.util.plot`)
124136
axis: matplotlib.axes._subplots.AxesSubplot, optional
125137
axis to use
138+
mask_distance: float, optional
139+
Only regions are plotted that are closer to any of the data points than this distance,
140+
relative to overall plot size. For instance, to only plot values
141+
at the centroids, use mask_distance=0.01. If None, the plot is not masked.
142+
Default is 0.01.
126143
kwargs: optional
127144
arguments for pcolormesh matplotlib function
128145
used in event plots or for plot function used in centroids plots
@@ -148,6 +165,7 @@ def plot_intensity(
148165
crs_epsg,
149166
axis,
150167
adapt_fontsize=adapt_fontsize,
168+
mask_distance=mask_distance,
151169
**kwargs,
152170
)
153171
if centr is not None:
@@ -157,7 +175,15 @@ def plot_intensity(
157175

158176
raise ValueError("Provide one event id or one centroid id.")
159177

160-
def plot_fraction(self, event=None, centr=None, smooth=True, axis=None, **kwargs):
178+
def plot_fraction(
179+
self,
180+
event=None,
181+
centr=None,
182+
smooth=True,
183+
axis=None,
184+
mask_distance=0.01,
185+
**kwargs,
186+
):
161187
"""Plot fraction values for a selected event or centroid.
162188
163189
Parameters
@@ -179,6 +205,11 @@ def plot_fraction(self, event=None, centr=None, smooth=True, axis=None, **kwargs
179205
in module `climada.util.plot`)
180206
axis: matplotlib.axes._subplots.AxesSubplot, optional
181207
axis to use
208+
mask_distance: float, optional
209+
Relative distance (with respect to maximal map extent in longitude or latitude) to data
210+
points above which plot should not display values. For instance, to only plot values
211+
at the centroids, use mask_distance=0.01. If None, the plot is not masked.
212+
Default is None.
182213
kwargs: optional
183214
arguments for pcolormesh matplotlib function
184215
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
196227
if isinstance(event, str):
197228
event = self.get_event_id(event)
198229
return self._event_plot(
199-
event, self.fraction, col_label, smooth, axis, **kwargs
230+
event,
231+
self.fraction,
232+
col_label,
233+
smooth,
234+
axis,
235+
mask_distance=mask_distance,
236+
**kwargs,
200237
)
201238
if centr is not None:
202239
if isinstance(centr, tuple):
@@ -215,6 +252,7 @@ def _event_plot(
215252
axis=None,
216253
figsize=(9, 13),
217254
adapt_fontsize=True,
255+
mask_distance=0.01,
218256
**kwargs,
219257
):
220258
"""Plot an event of the input matrix.
@@ -236,6 +274,11 @@ def _event_plot(
236274
axis to use
237275
figsize: tuple, optional
238276
figure size for plt.subplots
277+
mask_distance: float, optional
278+
Only regions are plotted that are closer to any of the data points than this distance,
279+
relative to overall plot size. For instance, to only plot values
280+
at the centroids, use mask_distance=0.01. If None, the plot is not masked.
281+
Default is None.
239282
kwargs: optional
240283
arguments for pcolormesh matplotlib function
241284
@@ -283,6 +326,7 @@ def _event_plot(
283326
figsize=figsize,
284327
proj=crs_espg,
285328
adapt_fontsize=adapt_fontsize,
329+
mask_distance=mask_distance,
286330
**kwargs,
287331
)
288332

climada/util/plot.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
from mpl_toolkits.axes_grid1 import make_axes_locatable
4848
from rasterio.crs import CRS
4949
from scipy.interpolate import griddata
50+
from scipy.spatial import cKDTree
5051
from shapely.geometry import box
5152

5253
import climada.util.coordinates as u_coord
@@ -337,6 +338,7 @@ def geo_im_from_array(
337338
axes=None,
338339
figsize=(9, 13),
339340
adapt_fontsize=True,
341+
mask_distance=0.01,
340342
**kwargs,
341343
):
342344
"""Image(s) plot defined in array(s) over input coordinates.
@@ -368,6 +370,11 @@ def geo_im_from_array(
368370
adapt_fontsize : bool, optional
369371
If set to true, the size of the fonts will be adapted to the size of the figure. Otherwise
370372
the default matplotlib font size is used. Default is True.
373+
mask_distance: float, optional
374+
Only regions are plotted that are closer to any of the data points than this distance,
375+
relative to overall plot size. For instance, to only plot values
376+
at the centroids, use mask_distance=0.01. If None, the plot is not masked.
377+
Default is 0.01.
371378
**kwargs
372379
arbitrary keyword arguments for pcolormesh matplotlib function
373380
@@ -448,6 +455,17 @@ def geo_im_from_array(
448455
(grid_x, grid_y),
449456
fill_value=min_value,
450457
)
458+
# Compute distance of each grid point to the nearest known point
459+
if mask_distance is not None:
460+
tree = cKDTree(np.array((coord[:, 1], coord[:, 0])).T)
461+
distances, _ = tree.query(
462+
np.c_[grid_x.ravel(), grid_y.ravel()],
463+
p=2, # for plotting squares and not sphere around centroids use p=np.inf
464+
)
465+
threshold = (
466+
max(extent[1] - extent[0], extent[3] - extent[2]) * mask_distance
467+
)
468+
grid_im[(distances.reshape(grid_im.shape) > threshold)] = min_value
451469
else:
452470
grid_x = coord[:, 1].reshape((width, height)).transpose()
453471
grid_y = coord[:, 0].reshape((width, height)).transpose()
@@ -477,7 +495,7 @@ def geo_im_from_array(
477495
)
478496
# handle NaNs in griddata
479497
color_nan = "gainsboro"
480-
if np.any(np.isnan(x) for x in grid_im):
498+
if np.isnan(grid_im).any():
481499
no_data_patch = mpatches.Patch(
482500
facecolor=color_nan, edgecolor="black", label="NaN"
483501
)
@@ -1086,6 +1104,7 @@ def plot_from_gdf(
10861104
axis=None,
10871105
figsize=(9, 13),
10881106
adapt_fontsize=True,
1107+
mask_distance=0.01,
10891108
**kwargs,
10901109
):
10911110
"""Plot several subplots from different columns of a GeoDataFrame, e.g., for
@@ -1108,6 +1127,11 @@ def plot_from_gdf(
11081127
adapt_fontsize: bool, optional
11091128
If set to true, the size of the fonts will be adapted to the size of the figure.
11101129
Otherwise the default matplotlib font size is used. Default is True.
1130+
mask_distance: float, optional
1131+
Relative distance (with respect to maximal map extent in longitude or latitude) to data
1132+
points above which plot should not display values. For instance, to only plot values
1133+
at the centroids, use mask_distance=0.01. If None, the plot is not masked.
1134+
Default is 0.01.
11111135
kwargs: optional
11121136
Arguments for pcolormesh matplotlib function used in event plots.
11131137
@@ -1168,6 +1192,7 @@ def plot_from_gdf(
11681192
axes=axis,
11691193
figsize=figsize,
11701194
adapt_fontsize=adapt_fontsize,
1195+
mask_distance=mask_distance,
11711196
**kwargs,
11721197
)
11731198

0 commit comments

Comments
 (0)