[英]Flexible map ticklables with cartopy
我經常發現自己需要繪制(大量)各種區域和區域大小的地圖。 我希望這些地圖具有指示經度和緯度的刻度標簽(類似於此示例: 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, 10), 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, 10), filename='test4.png') # not nice but somewhat okay
auto_labeling(np.linspace(-120, 120, 10), np.linspace(-70, 70, 10), filename='test5.png') # nice
# auto_labeling(np.linspace(-180, 180, 10), np.linspace(-90, 90, 10), 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, 10), 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(lon), min(lat), 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, 120, 60), np.arange(-70, 70, 30), filename='test5.png') # nice
好的,@r-beginners 的set_extend
使我走上了正確的軌道。 我仍然不明白正在發生的一切,但有兩件事似乎很重要:
我還添加了一個偏移參數,用於處理@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, lat, 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, data, transform=ccrs.PlateCarree(), 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, 2.5), 'test1.png', 1, 1)
auto_labeling(np.arange(-120, 120+2.5, 2.5), np.arange(30, 70+2.5, 2.5), 'test2.png')
auto_labeling(np.arange(-120, 120+2.5, 2.5), np.arange(-70, 70+2.5, 2.5), 'test3.png')
auto_labeling(np.arange(-180+1.25, 180, 2.5), np.arange(-90+1.25, 90, 2.5), 'test4.png', 2, 3) # offset is ignored for this case
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.