2

I've plotted a high-latitude non-rectagular cartopy map based off this stackoverflow question.

For some reason, I'm not getting any x and y longitude/latitude labels even though I want labels on the left/bottom axes of the plot.

Here is the code I am using to produce this figure:

import numpy as np
import cartopy
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
import matplotlib.ticker as mticker
import cartopy.feature as cf

"""
Plot Alaska
"""

# Map View Using Cartopy
fig = plt.figure(figsize=(8,6))

xmin=-163
xmax=-120
ymin=50
ymax=71

proj = ccrs.LambertConformal(central_longitude=(xmin+xmax)/2, central_latitude=(ymin+ymax)/2)
ax = fig.add_subplot(1, 1, 1, projection=proj)
n = 20
aoi = mpath.Path(
    list(zip(np.linspace(xmin,xmax, n), np.full(n,ymax))) + \
    list(zip(np.full(n,xmax), np.linspace(ymax,ymin, n))) + \
    list(zip(np.linspace(xmax,xmin, n), np.full(n,ymin))) + \
    list(zip(np.full(n,xmin), np.linspace(ymin,ymax, n)))
)
ax.set_boundary(aoi, transform=ccrs.PlateCarree()) 

# Plot Ocean Borders
ocean = cf.NaturalEarthFeature('physical','ocean',scale='50m',edgecolor='k',facecolor='lightblue',lw=1,linestyle='-')
ax.add_feature(ocean)
# Colored Land Background
land = cf.NaturalEarthFeature('physical','land',scale='50m',facecolor='snow',lw=1,linestyle='--')
ax.add_feature(land)

ax.set_extent([xmin,xmax,ymin,ymax],crs=ccrs.PlateCarree())
ax.gridlines(draw_labels=True,crs=ccrs.PlateCarree(),x_inline=False,y_inline=False)
gl.xlocator = mticker.FixedLocator([-160,-150,-140,-130,-120])
gl.ylocator = mticker.FixedLocator([50,55,60,65,70])
gl.xformatter = LONGITUDE_FORMATTER
gl.yformatter = LATITUDE_FORMATTER

plt.show()

This is the figure you get:

fig no axes

How can I get my x and y axis labels to show up on a non-rectangular plot?

1 Answers1

2

You just need to set gl = ax.gridlines(draw_labels=True,crs=ccrs.PlateCarree(),x_inline=False,y_inline=False)

import numpy as np
import cartopy
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
import matplotlib.ticker as mticker
import matplotlib.path as mpath
import cartopy.feature as cf

"""
Plot Alaska
"""

# Map View Using Cartopy
fig = plt.figure(figsize=(8,6))

xmin=-163
xmax=-120
ymin=50
ymax=71

proj = ccrs.LambertConformal(central_longitude=(xmin+xmax)/2, central_latitude=(ymin+ymax)/2)
ax = fig.add_subplot(1, 1, 1, projection=proj)
n = 20
aoi = mpath.Path(
    list(zip(np.linspace(xmin,xmax, n), np.full(n,ymax))) + \
    list(zip(np.full(n,xmax), np.linspace(ymax,ymin, n))) + \
    list(zip(np.linspace(xmax,xmin, n), np.full(n,ymin))) + \
    list(zip(np.full(n,xmin), np.linspace(ymin,ymax, n)))
)
ax.set_boundary(aoi, transform=ccrs.PlateCarree())

# Plot Ocean Borders
ocean = cf.NaturalEarthFeature('physical','ocean',scale='50m',edgecolor='k',facecolor='lightblue',lw=1,linestyle='-')
ax.add_feature(ocean)
# Colored Land Background
land = cf.NaturalEarthFeature('physical','land',scale='50m',facecolor='snow',lw=1,linestyle='--')
ax.add_feature(land)

ax.set_extent([xmin,xmax,ymin,ymax],crs=ccrs.PlateCarree())
# Set gridlines to variable so you can manipulate them
gl = ax.gridlines(draw_labels=True,crs=ccrs.PlateCarree(),x_inline=False,y_inline=False)
gl.xlocator = mticker.FixedLocator([-160,-150,-140,-130,-120])
gl.ylocator = mticker.FixedLocator([50,55,60,65,70])
gl.xformatter = LONGITUDE_FORMATTER
gl.yformatter = LATITUDE_FORMATTER

plt.show()

alaska with labels


Edit:

Thanks to @swatchai, the following code snippet takes care of the right-side y-labels:

# Generate the plot to enable access to the labels' attributes
plt.draw()

# Iterate for the y-labels
# The right labels have x coordinates > 0
# The left labels < 0
for ea in gl.ylabel_artists:
    right_label = ea.get_position()[0] > 0
    # print(ea, ea.get_position()[0], ea.get_visible())
    if right_label:
        ea.set_visible(False)

plt.show()

Check out @swatchai's full answer for more details!

  • Yeah... Thank you because that was what I originally had but I've been panic debugging all day and took that out for some reason. That does not change the figure for me. – kbiegseismic Feb 28 '23 at 01:09
  • 1
    Adding the gl = ax.gridline() it doesn't work for you then? What Cartopy version are you on? I am using 0.21.1 – just_another_profile Feb 28 '23 at 01:16
  • You know what ... that might be it. It appears I have an older version 0.18.0. It's going to take a bit to update my env I suspect. – kbiegseismic Feb 28 '23 at 01:19
  • 2
    Oh heck yes! Thank you. Upgrading the package definitely worked. – kbiegseismic Feb 28 '23 at 01:32
  • Awesome! Also about your labels only in the bottom and left axes, you might want to check out https://github.com/SciTools/cartopy/issues/1722. I can eliminate the top labels with ``gl.top_labels = False`` but I can't get it to work for the right labels using ``gl.right_labels = False``...not sure what is going on – just_another_profile Feb 28 '23 at 01:37
  • I noticed that as well. My workaround since I need the figure done tonight was to delete individual labels in illustrator, but I'd be interested to see if anyone else can solve it. – kbiegseismic Feb 28 '23 at 02:49
  • I think it has to do with ax.set_boundary(), probably another question for SO... – just_another_profile Feb 28 '23 at 02:52
  • 1
    Please check my answer to your question, and try applying the workaround here to get the required plot. And I will vote up your answer. – swatchai Mar 01 '23 at 07:17