简体   繁体   中英

Placement of latitude labels in cartopy with polar stereographic projection

I am trying to figure out how to change the placement of gridline labels (more specifically, latitude labels) in cartopy when using a polar stereographic projection ( NorthPolarStereo ). My axis currently looks like this:

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

# Helper function
# from https://nordicesmhub.github.io/NEGI-Abisko-2019/training/example_NorthPolarStereo_projection.html
def polarCentral_set_latlim(lat_lims, ax):
    ax.set_extent([-180, 180, lat_lims[0], lat_lims[1]], ccrs.PlateCarree())
    theta = np.linspace(0, 2*np.pi, 100)
    center, radius = [0.5, 0.5], 0.5
    verts = np.vstack([np.sin(theta), np.cos(theta)]).T
    circle = mpath.Path(verts * radius + center)
    ax.set_boundary(circle, transform=ax.transAxes)

fig = plt.figure(figsize=(6,6))
ax = fig.add_subplot(1,1,1,projection=ccrs.NorthPolarStereo(central_longitude=0))
ax.coastlines(linewidth=0.5,color='k')
ax.gridlines(color='C7',lw=1,ls=':',draw_labels=True,rotate_labels=False,ylocs=[60,70,80])
polarCentral_set_latlim((50,90),ax)

具有默认网格线标签位置的极地立体图

Oddly, the latitude labels are always plotted at about 150E even if the central_longitude is set to a different value. Preferably, I'd like to align them with the 180th meridian (similar to the labels in this plot ) but I cannot find an option in the documentation of the gridlines function to set their position. Did I overlook something or would I have to place them manually with plt.text()

After the gridlines is created, some labels can be accessed and moved to new positions. I use alternate method to define the circular boundary of the plot in order not to interfere with gridlines' labels.

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

# Value for r_extent is obtained by trial and error
# get it with `ax.get_ylim()` after running this code
r_extent = 4651194.319
r_extent *= 1.005       #increase a bit for better result

# Projection settings  
lonlat_proj = ccrs.PlateCarree()
use_proj = ccrs.NorthPolarStereo(central_longitude=0)
fig = plt.figure(figsize=[7, 7])
ax = plt.subplot(1, 1, 1, projection=use_proj)
ax.set_extent([-180, 180, 50, 90], lonlat_proj)

#ax.stock_img() # add bluemarble image
ax.coastlines(lw=0.5, color="black", zorder=20) # add coastlines

# draw graticule (meridian and parallel lines)
gls = ax.gridlines(draw_labels=True, crs=lonlat_proj, lw=1, color="gray",
        y_inline=True, xlocs=range(-180,180,30), ylocs=range(0,90,10))

# set the plot limits
ax.set_xlim(-r_extent, r_extent)
ax.set_ylim(-r_extent, r_extent)

# Prep circular boundary
circle_path = mpath.Path.unit_circle()
circle_path = mpath.Path(circle_path.vertices.copy() * r_extent,
                           circle_path.codes.copy())

#set circular boundary
#this method will not interfere with the gridlines' labels 
ax.set_boundary(circle_path)
ax.set_frame_on(False)  #hide the boundary frame

plt.draw()  # Enable the use of `gl._labels`

# Reposition the tick labels
# Labels at 150d meridian will be moved to 180d
for ea in gls._labels:
    # No _labels if not run `plt.draw()`
    pos = ea[2].get_position()
    #print("Position:", pos[0], pos[1])
    if (pos[0]==150):
        ea[2].set_position([180, pos[1]])

plt.show()

输出1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM