带有地图的灵活地图刻度

问题描述

我经常会发现自己需要绘制各种区域和区域大小的(很多)地图。我希望这些地图具有刻度标签,以指示经度和纬度(类似于此示例:https://scitools.org.uk/cartopy/docs/v0.15/examples/tick_labels.html)。

但是,建议的解决方案对我而言不起作用,因为它需要有关该区域扩展的先验知识。多年来,我已经写了几种过于复杂的函数,以便尝试以灵活的方式进行这项工作。 所以我现在想知道的是:是否有一种简单的解决方案将纬度和经度刻度标签放置到变量扩展图上?

这有点接近,但仍然很不可靠:

import numpy as np
import cartopy.crs as ccrs 
from cartopy.mpl.ticker import LongitudeFormatter,LatitudeFormatter
import matplotlib.pyplot as plt


def auto_labeling(lon=np.linspace(-10,40,10),lat=np.linspace(30,70,filename='test1.png'):
    proj = ccrs.PlateCarree(central_longitude=0)
    data = np.ones((len(lon),len(lat)))
    ax = plt.subplot(projection=proj)
    ax.pcolormesh(lon,lat,data,transform=ccrs.PlateCarree(),alpha=.5)
    ax.coastlines()
    ax.set_xticks(ax.get_xticks(),crs=ccrs.PlateCarree())
    ax.set_yticks(ax.get_yticks(),crs=ccrs.PlateCarree())
    lon_formatter = LongitudeFormatter()
    lat_formatter = LatitudeFormatter()
    ax.xaxis.set_major_formatter(lon_formatter)
    ax.yaxis.set_major_formatter(lat_formatter)
    plt.savefig(filename,dpi=300)
    plt.close()


if __name__ == '__main__':
    auto_labeling(filename='test3.png')  # nice
    auto_labeling(np.linspace(-120,120,filename='test4.png')  # not nice but somewhat okay
    auto_labeling(np.linspace(-120,np.linspace(-70,filename='test5.png')  # nice
    # auto_labeling(np.linspace(-180,180,np.linspace(-90,90,filename='test6.png')  # fails

解决方法

PlateCaree使用ax.set_extent([min(lon),max(lon),min(lat),max(lat)])扩展区域。 ax.pcolormesh()被注释掉,因为它会导致错误。我对这一点还不了解。

import numpy as np
import cartopy.crs as ccrs 
from cartopy.mpl.ticker import LongitudeFormatter,LatitudeFormatter
import matplotlib.pyplot as plt

def auto_labeling(lon=np.arange(-10,40,10),lat=np.arange(30,70,filename='test1.png'):
    proj = ccrs.PlateCarree(central_longitude=0)
    data = np.ones((len(lon),len(lat)))
    plt.figure(figsize=(16,9))
    ax = plt.subplot(projection=proj)
    ax.set_extent([min(lon),max(lat)])
    # ax.pcolormesh(lon,lat,data,transform=ccrs.PlateCarree(),alpha=.5)
    ax.coastlines()
    ax.set_xticks(lon,crs=ccrs.PlateCarree())
    ax.set_yticks(lat,crs=ccrs.PlateCarree())
    lon_formatter = LongitudeFormatter()
    lat_formatter = LatitudeFormatter()
    ax.xaxis.set_major_formatter(lon_formatter)
    ax.yaxis.set_major_formatter(lat_formatter)
    # plt.savefig(filename,dpi=300)
    # plt.close()
    plt.show()


if __name__ == '__main__':
    auto_labeling(filename='test3.png')  # nice
    auto_labeling(np.arange(-120,120,60),filename='test4.png')  # not nice but somewhat okay
    auto_labeling(np.arange(-120,np.arange(-70,30),filename='test5.png')  # nice

enter image description here

enter image description here

enter image description here

,

好吧,@ r-beginners的set_extend使我走上了正确的轨道。我仍然不了解正在发生的一切,但似乎有两点很重要:

  • 自动创建的刻度线必须限制为[-180,180]&[-90,90],否则我也会收到错误消息
  • 设置扩展名可使该图在我尝试过的所有情况下看起来都很好

我还添加了一个offset参数,该参数处理默认情况下@swatchai会在每个方向上将范围扩大和扩大一半的网格单元格的问题。我认为有时候看起来还不错,因此还有更多可能。

import numpy as np
import cartopy.crs as ccrs
from cartopy.mpl.ticker import LongitudeFormatter,LatitudeFormatter
import matplotlib.pyplot as plt


def auto_labeling(lon,filename,offset_dx=.5,offset_dy=.5):
    assert len(np.unique(lon[1:] - lon[:-1])) == 1
    assert len(np.unique(lat[1:] - lat[:-1])) == 1
    yy,xx = np.meshgrid(lat,lon)
    data = np.ones((len(lon),len(lat)))

    proj = ccrs.PlateCarree(central_longitude=0)
    ax = plt.subplot(projection=proj)
    ax.pcolormesh(xx,yy,alpha=.5)
    ax.coastlines()

    xticks = ax.get_xticks()
    yticks = ax.get_yticks()
    xticks = xticks[(xticks>=-180) & (xticks<=180)]
    yticks = yticks[(yticks>=-90) & (yticks<=90)]
    ax.set_xticks(xticks,crs=ccrs.PlateCarree())
    ax.set_yticks(yticks,crs=ccrs.PlateCarree())

    lon_formatter = LongitudeFormatter()
    lat_formatter = LatitudeFormatter()
    ax.xaxis.set_major_formatter(lon_formatter)
    ax.yaxis.set_major_formatter(lat_formatter)

    # set the plot extend
    dx = (lon[1] - lon[0])*offset_dx
    dy = (lat[1] - lat[0])*offset_dy
    lon_min = max([-180,min(lon) - dx])
    lon_max = min([180,max(lon) + dx])
    lat_min = max([-90,min(lat) - dy])
    lat_max = min([90,max(lat) + dy])
    ax.set_xlim(lon_min,lon_max)
    ax.set_ylim(lat_min,lat_max)

    plt.savefig(filename,dpi=300)
    plt.close()

if __name__ == '__main__':
    auto_labeling(np.arange(-10,40+2.5,2.5),np.arange(30,70+2.5,'test1.png',1,1)
    auto_labeling(np.arange(-120,120+2.5,'test2.png')
    auto_labeling(np.arange(-120,'test3.png')
    auto_labeling(np.arange(-180+1.25,180,np.arange(-90+1.25,90,'test4.png',2,3)  # offset is ignored for this case

figure1 figure2 figure3 figure4

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...