【问题标题】:Placement of latitude labels in cartopy with polar stereographic projection使用极立体投影在 cartopy 中放置纬度标签
【发布时间】:2023-02-20 21:01:55
【问题描述】:

我试图弄清楚如何在使用极立体投影 (NorthPolarStereo) 时更改 cartopy 中网格线标签(更具体地说,纬度标签)的位置。我的轴目前看起来像这样:

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)

奇怪的是,即使 central_longitude 设置为不同的值,纬度标签始终绘制在大约 150E 处。最好,我想将它们与第 180 条子午线对齐(类似于 this plot 中的标签),但我在 gridlines 函数的文档中找不到设置它们位置的选项。我是不是忽略了什么,还是必须用plt.text()手动放置它们?

【问题讨论】:

    标签: python matplotlib cartopy


    【解决方案1】:

    创建gridlines后,可以访问一些标签并将其移动到新位置。 我使用替代方法来定义绘图的圆形边界,以免干扰网格线的标签。

    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()
    

    【讨论】:

      【解决方案2】:

      可能是因为我使用了 cartopy 版本 (0.21.1),但@swatchai 的回答对我不起作用。然而,可以做一个微小的改变,并且会很好地工作。

      plt.draw()
      for ea in gls.label_artists:
          # return ea of mpl.text type, e.g. Text(135, 30, '30°N') 
          pos = ea.get_position()
          if pos[0] == 135:
              ea.set_position([180, pos[1]])
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-29
        • 1970-01-01
        • 2021-04-03
        • 1970-01-01
        • 2012-12-28
        • 2015-10-05
        • 1970-01-01
        相关资源
        最近更新 更多