Description
1. A bug: the region border is not projected
When using 'projection': cartopy.crs.Mercator()
in plot_args
to csep.utils.plots.plot_spatial_dataset
(i.e., via csep.core.forecasts.GriddedForecast.plot
, the region boundary disappears. This doesn't happen if not specifying this argument (i.e., when PlateCaree is used).
Suggested fix: add transform=cartopy.crs.PlateCarree()
to the .plot() command here.
2. A (faster) alternative to using projections
Instead of using a fancy projections (i.e. everything else than PlateCaree), you may consider to simply scale the axes according to the currently shown region:
import cartopy.feature as cfeature
fig = plt.figure()
# Set projection
ax = plt.axes(projection=cartopy.crs.PlateCarree())
# Re-aspect plot (only for plain matplotlib plots, or when using PlateCarree)
LATKM = 110.574
lat_region = <approximate latitude at the center of the plot>
ax.set_aspect(1 / (LATKM / 111.320 * np.cos(np.deg2rad(lat_region))))
ax.add_feature(cfeature.LAND)
ax.add_feature(cfeature.COASTLINE, ...)
ax.coastlines(resolution='50m', ...)
ax.add_feature(cfeature.BORDERS, ...)
ax.scatter(...)
(Note that you don't need to specify the transform=cartopy.crs.PlateCarree()
argument in the plot/scatter/pcolor functions, but you can.)
I found this approach completely sufficient at country-level zoom levels (or closer). By setting the correct aspect ratio at the current latitude, you'll hardly notice a difference to projection-based plots at such zoom levels (unless you plot larger countries like Russia, etc. 😉). Plotting is also faster (~2-3x), as it avoids using more expensive transform objects (such as Mercator(), Orthographic(), you name it); note that this speed increase is independent of the number of plotted events / grid cells. (Btw: In case you want to benchmark the plotting speed, be aware that cartopy uses some sort of memoizing, so you need to reload the module every time.)
Suggested "fix": Maybe we can implement an intelligent switch (and/or an arg) to use plain PlateCaree + set_aspect. Essentially, this would need to happen in csep.utils.plots.plot_basemap
.