Skip to content
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

Lat and lon labels in LambertConformal at edges not shown #1803

Closed
MiriamSterl opened this issue Jun 10, 2021 · 1 comment
Closed

Lat and lon labels in LambertConformal at edges not shown #1803

MiriamSterl opened this issue Jun 10, 2021 · 1 comment

Comments

@MiriamSterl
Copy link

Description

I want to plot data in the LambertConformal projection, 'cut out' the figure into the shape of the projection, and add axis labels. However, the labels that belong in the corners (minimum and maximum latitude and longitude) are not shown. See image below: I would like to also have the labels for 40N, 80N, 80W and 20E. These are included in the array that I give as input to the xlocator and ylocator of the gridliner object. How can I ensure that these labels in the corners are also shown?

image

Code to reproduce

import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import matplotlib.path as mpath
import matplotlib.ticker as mticker

bounds_lon = [-80,20]
bounds_lat = [40,80]
projection = ccrs.LambertConformal(central_longitude=np.mean(bounds_lon),central_latitude=np.mean(bounds_lat))
fig, ax = plt.subplots(1,1,figsize=(24,8),subplot_kw={'projection': projection})
ax.coastlines()

# Create nicely shaped boundaries (based on https://stackoverflow.com/questions/65687535/how-do-i-limit-the-longitude-extent-in-cartopys-lambertconformal-and-keep-the-c)
rect = mpath.Path([[bounds_lon[0], bounds_lat[0]],
                   [bounds_lon[1], bounds_lat[0]],
                   [bounds_lon[1], bounds_lat[1]],
                   [bounds_lon[0], bounds_lat[1]],
                   [bounds_lon[0], bounds_lat[0]],
                   ]).interpolated(20)
proj_to_data = ccrs.PlateCarree()._as_mpl_transform(ax) - ax.transData
rect_in_target = proj_to_data.transform_path(rect)
ax.set_boundary(rect_in_target)
ax.set_extent([bounds_lon[0], bounds_lon[1], bounds_lat[0] - 15, bounds_lat[1]])

# Set axes labels
gl = ax.gridlines(crs=ccrs.PlateCarree(), x_inline=False, y_inline=False,
                  linewidth=2, color='gray', alpha=0.5, linestyle='--')
gl.xlocator = mticker.FixedLocator(np.arange(bounds_lon[0],bounds_lon[1]+0.1,10))
gl.ylocator = mticker.FixedLocator(np.arange(bounds_lat[0],bounds_lat[1]+0.1,10))
gl.left_labels = True
gl.bottom_labels = True

plt.show()

Traceback


Full environment definition

Operating system

Cartopy version

conda list

pip list

@pgf
Copy link

pgf commented Jun 10, 2021

The gridlines method seems to place labels only where gridlines are drawn.
AFAIK release 0.20 will introduce a new gridliner that hopefully fix these issues (#1537).
A possible workaround in the meantime is to define a slightly larger rectangle for the boundary:

import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import matplotlib.path as mpath
import matplotlib.ticker as mticker

eps=6.0e-2
bounds_lon = [-80,20]
bounds_lat = [40,80]
rect_lon=[bounds_lon[0]-eps, bounds_lon[1]+eps]
rect_lat=[bounds_lat[0]-eps, bounds_lat[1]+eps]
projection = ccrs.LambertConformal(central_longitude=np.mean(bounds_lon),central_latitude=np.mean(bounds_lat))
fig, ax = plt.subplots(1,1,figsize=(24,8),subplot_kw={'projection': projection})
ax.coastlines()

# Create nicely shaped boundaries (based on https://stackoverflow.com/questions/65687535/how-do-i-limit-the-longitude-extent-in-cartopys-lambertconformal-and-keep-the-c)
rect = mpath.Path([[rect_lon[0], rect_lat[0]],
    [rect_lon[1], rect_lat[0]],
    [rect_lon[1], rect_lat[1]],
    [rect_lon[0], rect_lat[1]],
    [rect_lon[0], rect_lat[0]],
    ]).interpolated(20)
proj_to_data = ccrs.PlateCarree()._as_mpl_transform(ax) - ax.transData
rect_in_target = proj_to_data.transform_path(rect)
ax.set_boundary(rect_in_target)
ax.set_extent([bounds_lon[0], bounds_lon[1], bounds_lat[0] - 15, bounds_lat[1]])

# Set axes labels
gl = ax.gridlines(crs=ccrs.PlateCarree(), x_inline=False, y_inline=False,
                  linewidth=2, color='gray', alpha=0.5, linestyle='--')
gl.xlocator = mticker.FixedLocator(np.arange(bounds_lon[0],bounds_lon[1]+0.1,10))
gl.ylocator = mticker.FixedLocator(np.arange(bounds_lat[0],bounds_lat[1]+0.1,10))
gl.left_labels = True
gl.bottom_labels = True

plt.show()

Here is the result:
test_boundary
Maybe not quite publication quality.
Fill free to experiment with the eps value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants