Skip to content

missing region border in plots #110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 6, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 45 additions & 14 deletions csep/utils/plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,8 @@ def get_hist(x, mws, normed=True):
pyplot.show()

def plot_basemap(basemap, extent, ax=None, coastline=True, borders=False, linecolor='black', linewidth=True,
grid=False, grid_labels=False, set_global=False, show=False):
grid=False, grid_labels=False, set_global=False, show=False, projection=ccrs.PlateCarree(), apprx=False,
central_latitude=0.0):
""" Wrapper function for multiple cartopy base plots, including access to standard raster webservices

Args:
Expand All @@ -568,16 +569,29 @@ def plot_basemap(basemap, extent, ax=None, coastline=True, borders=False, linec
linecolor (str): Color of borders and coast lines. default 'black',
grid (bool): Draws a grid in the basemap
grid_labels (bool): Annotate grid values
apprx (bool): If true, approximates transformation by setting aspect ratio of axes based on middle latitude
central_latitude (float): average latitude from plotting region

Returns:
:class:`matplotlib.pyplot.ax` object

"""
if ax is None:
fig = pyplot.figure()
ax = fig.add_subplot(111, projection=ccrs.PlateCarree(central_longitude=0.0))
if apprx:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add & projection == ccrs.PlateCarree()? (not needed if you are sure that plot_basemap() will never be called by a user)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the default arg is projection=ccrs.PlateCarree. I believe its good as Bill left it, to accept different projections. Also the default platecarree looks good, for quick plotting without worrying about projections.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think plot_basemap will probably be called by other users especially if they are trying to plot catalogs on top of forecasts or other data sets. is there a downside to letting users choose projections in the plot_basemap function?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant is: the 'fast'/apprx "projection" works by rescaling the axes. This rescaling is incompatible with any other "true" (non-PlateCaree) projection, which should be caught by adding & projection == ccrs.PlateCarree() to the if statement.

Copy link
Collaborator Author

@wsavran wsavran Apr 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats a good point. in the other functions i handled that case by forcing projection=ccrs.PlateCarree(). for example, in plot_catalog(). not sure why i didn't do that in basemap. also, if the user chooses the fast option, we should force PlateCarree().

now that im thinking about it, there are some other parameters that might lose continuity between these cartopy enhanced calls, eg, extent

projection = ccrs.PlateCarree()
fig = pyplot.figure()
ax = fig.add_subplot(111, projection=projection)
# Re-aspect plot (only for plain matplotlib plots, or when using PlateCarree)
LATKM = 110.574
ax.set_aspect(111.320 * numpy.cos(numpy.deg2rad(central_latitude)) / LATKM)
else:
fig = pyplot.figure()
ax = fig.add_subplot(111, projection=projection)

if set_global:
ax.set_global()
else:
ax.set_extent(extents=extent, crs=ccrs.PlateCarree())

try:
# Set adaptive scaling
Expand Down Expand Up @@ -613,7 +627,6 @@ def plot_basemap(basemap, extent, ax=None, coastline=True, borders=False, linec

return ax


def plot_catalog(catalog, ax=None, show=False, extent=None, set_global=False, plot_args=None):
""" Plot catalog in a region

Expand All @@ -629,7 +642,8 @@ def plot_catalog(catalog, ax=None, show=False, extent=None, set_global=False, pl
- :title: :class:`str` - default :class:`catalog.name`
- :title_size: :class:`int` - default 10
- :filename: :class:`str` - File to save figure. default None
- :projection: :class:`cartopy.crs.Projection` - default :class:`cartopy.crs.PlateCarree`
- :projection: :class:`cartopy.crs.Projection` - default :class:`cartopy.crs.PlateCarree`. Note: this can be
'fast' to apply an approximate transformation of axes.
- :grid: :class:`bool` - default True
- :grid_labels: :class:`bool` - default True
- :marker: :class:`str` - Marker type
Expand Down Expand Up @@ -689,22 +703,32 @@ def plot_catalog(catalog, ax=None, show=False, extent=None, set_global=False, pl
pass

if extent is None:
dh = (bbox[1] - bbox[0])/20.
dh = (bbox[1] - bbox[0]) / 20.
dv = (bbox[3] - bbox[2]) / 20.
extent = [bbox[0] - dh, bbox[1]+dh, bbox[2] -dv, bbox[3] + dv]

apprx = False
central_latitude = 0.0
if projection == 'fast':
projection = ccrs.PlateCarree()
apprx = True
n_lats = len(catalog.region.ys) // 2
central_latitude = catalog.region.ys[n_lats]

# Instantiage GeoAxes object
if ax is None:
fig = pyplot.figure(figsize=figsize)
ax = fig.add_subplot(111, projection=projection)
if set_global:
ax.set_global()
else:
ax.set_extent(extents=extent, crs=ccrs.PlateCarree()) # Defined extent always in lat/lon

if set_global:
ax.set_global()
else:
ax.set_extent(extents=extent, crs=ccrs.PlateCarree()) # Defined extent always in lat/lon
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should the crs here be projection and not ccrs.PlateCarree()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the docs: "Set the extent (x0, x1, y0, y1) of the map in the given coordinate system. [scitools.org.uk/cartopy/docs/...]. By default (crs=None), it would take over the projection of the axis (i.e. projection), but since the extent will be - in our case - (always?) specified in the same coordinate system as the original data (i.e. PlateCaree()), it is good as is.

See also stackoverflow.com.


# Basemap plotting
ax = plot_basemap(basemap, extent, ax=ax, coastline=coastline, borders=borders,
linecolor=linecolor, linewidth=linewidth)
linecolor=linecolor, linewidth=linewidth, projection=projection, apprx=apprx,
central_latitude=central_latitude)

# Scaling function
mw_range = [min(catalog.get_magnitudes()), max(catalog.get_magnitudes())]
Expand Down Expand Up @@ -758,7 +782,6 @@ def size_map(markersize, values, scale):

return ax


def plot_spatial_dataset(gridded, region, ax=None, show=False, extent=None, set_global=False, plot_args=None):
""" Plot spatial dataset such as data from a gridded forecast

Expand Down Expand Up @@ -823,6 +846,13 @@ def plot_spatial_dataset(gridded, region, ax=None, show=False, extent=None, set_
alpha = plot_args.get('alpha', 1)
alpha_exp = plot_args.get('alpha_exp', 0)

apprx = False
central_latitude = 0.0
if projection == 'fast':
projection = ccrs.PlateCarree()
apprx = True
n_lats = len(region.ys) // 2
central_latitude = region.ys[n_lats]

# Instantiage GeoAxes object
if ax is None:
Expand All @@ -838,7 +868,8 @@ def plot_spatial_dataset(gridded, region, ax=None, show=False, extent=None, set_

# Basemap plotting
ax = plot_basemap(basemap, extent, ax=ax, coastline=coastline, borders=borders,
linecolor=linecolor, linewidth=linewidth)
linecolor=linecolor, linewidth=linewidth, projection=projection, apprx=apprx,
central_latitude=central_latitude)

## Define colormap and transparency function
if isinstance(cmap, str) or not cmap:
Expand Down Expand Up @@ -874,7 +905,7 @@ def plot_spatial_dataset(gridded, region, ax=None, show=False, extent=None, set_

if region_border:
pts = region.tight_bbox()
ax.plot(pts[:,0], pts[:,1], lw=1, color='black')
ax.plot(pts[:,0], pts[:,1], lw=1, color='black', transform=ccrs.PlateCarree())

# matplotlib figure options
ax.set_title(title, y=1.06)
Expand Down