I'm trying to produce an orthographic figure using Cartopy. I have basically the entire thing working exactly the way I want it to...except for the labels on the longitude gridlines. While the convention for longitude is often to use 0 - 180 E or 0 - 180 W, the convention on other bodies can sometimes be 0 - 360 degrees. I want to adhere to the latter convention, as to be consistent with the longitude convention in the rest of my work.
My problem is that the LongitudeFormatter does not seem to have any option that allows me to simply plot longitude gridlines with 0 - 360 labels. The documentation does give an example of how to accomplish this with PlateCarree (here), but I am using orthographic projection, and attempting to apply the given example just tells me "This formatter cannot be used with non-rectangular projections." That being said, the LongitudeFormatter otherwise seems to work completely fine with the orthographic projection?
Here's a simplified example that demonstrates my question.
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy.mpl.ticker import (LongitudeFormatter, LatitudeFormatter,
LongitudeLocator,LatitudeLocator)
plotproj = ccrs.Orthographic(central_longitude=90, central_latitude=45)
mgeodetic = ccrs.Geodetic()
fig1,ax1 = plt.subplots(1,1,figsize=(10.0,10.0),constrained_layout=True,
subplot_kw={"projection":plotproj})
ax1.set_global()
#grid lines
longlocs = [0,30,60,90,120,150,180,210,240,270,300,330,360]
gl = ax1.gridlines(draw_labels=True,x_inline=True,
xpadding=0,ypadding=0,xlocs=longlocs)
gl.top_labels = False
gl.left_labels = False
gl.xlocator = LongitudeLocator(nbins=12)
gl.ylocator = LatitudeLocator(nbins=12)
gl.xformatter = LongitudeFormatter(auto_hide=False)
gl.yformatter = LatitudeFormatter(auto_hide=False)
ax1.invert_xaxis() #makes longitude run the opposite direction, necessary for my use case
This example produces the following figure:
I have tried the options available for the LongitudeFormatter.
direction_label = False
just makes the longitude run from 0 to 180 and -180 to 0.
dateline_direction_label
and zero_direction_label
only affect the 0 and 180 meridians.
cardinal_labels
is for replacing the existing E and W labels, but doesn't affect the values.
I feel like I must be overlooking something obvious- how do I plot 0 to 360 longitude labels?
Q: How do I plot 0 to 360 longitude labels?
A: You can replace the labels with new ones that meet your needs.
The code given below should do the trick.
Place it in before the line ax1.invert_xaxis()
.
fig1, ax1 = plt.subplots(1, 1, figsize=(10.0, 10.0), constrained_layout=True, subplot_kw={"projection": plotproj})
ax1.set_global()
#grid lines
gl = ax1.gridlines(draw_labels=True, x_inline=True, xpadding=0, ypadding=0)
gl.top_labels = False
gl.left_labels = False
gl.xlocator = LongitudeLocator(nbins=12)
gl.ylocator = LatitudeLocator(nbins=12)
gl.xformatter = LongitudeFormatter(auto_hide=False)
gl.yformatter = LatitudeFormatter(auto_hide=False)
# (Relevant code)
# Generate the plot to enable access to the labels' attributes
ax1.draw(fig1.canvas.get_renderer())
# The current labels and the new ones to use
# If you need degree symbol just add + "°"
rep_vals = {'150°W': str(360-150),
'120°W': str(360-120),
'90°W': str(360-90),
'60°W': str(360-60),
'30°W': str(360-30),
'0°': "0",
'30°E': "30",
'60°E': "60",
'90°E': "90",
'120°E': "120",
'150°E': "150"
}
# Iterate through the x-labels
for ea in gl.xlabel_artists:
#print(ea, ea.get_position()[0], ea.get_visible())
if ea.get_visible():
# If visible, replace it with new label
ea.set_text(rep_vals[ea.get_text()])
ax1.invert_xaxis()