Python & Cartopy问题:经纬度设置被忽略,绘图范围不符预期
解决Cartopy忽略指定经纬度范围的问题
问题描述
使用Cartopy绘图时,指定的经纬度范围参数被忽略,生成图像与预期的plotcorners=[-120, -30, 120, 80]范围不符。相关代码如下:
%matplotlib inline import matplotlib.pyplot as plt # matplotlib.pyplot ist ein Modul zum Erzeugen von Plots import numpy as np # numpy ist ein Modul zur Vereinfachung numerischer Berechnungen import xarray as xr # xarray ist das Modul zur Definition des xarray-Konstrukts import cartopy # cartopy dient zum Zeichnen von Landkarten import cartopy.crs as ccrs import cartopy.util as cu # cartopy.util wird benötigt, um ein Datenfeld zyklisch zu ergänzen, # also die erste Reihe von Werten entlang der Längengrade als letzte zu wiederholen from cartopy.mpl.gridliner import LongitudeFormatter, LatitudeFormatter # LongitudeFormatter und LatitudeFormatter werden zum Zeichnen der # Gitterlinien benötigt. import scipy.stats def cartopymap(corners): [leftlon, lowerlat, rightlon, upperlat] = corners central_lon = (leftlon+rightlon)/2 ax = plt.axes(projection=ccrs.PlateCarree()) ax.set_extent([leftlon, rightlon, lowerlat, upperlat]) ax.coastlines(resolution='110m', linewidth=1.0) lontics = np.arange(leftlon-10,rightlon,20) lattics = np.arange(0,101,10) # Gilt nur für Nordhemisphäre gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=1.5, color='gray', alpha=0.5, linestyle='--') gl.top_labels = False gl.right_labels = False gl.xlabel_style = {'size': 12} gl.ylabel_style = {'size': 12} gl.xformatter = LongitudeFormatter() gl.yformatter = LatitudeFormatter() return ax def plot_filled_contours_map(title, corners, Z, levz, colormap): fig = plt.figure(facecolor='1.', figsize=[10, 5]) map = cartopymap(corners) data, lon = cu.add_cyclic_point(Z.values, Z.lon.values) lat = Z.lat CP = map.contourf(lon, lat, data, levz, transform=ccrs.PlateCarree(), cmap=colormap, extend='both') map.coastlines() cbar = plt.colorbar(CP, ax=map, aspect=50, fraction=0.1) cbar.ax.tick_params(labelsize=10) plt.title(title, y=1.1, fontsize=14) ncfile = "monthly_v_2018.nc" tempdata = xr.open_dataset(ncfile) levz = [-20, -17.5, -15, -12.5, -10, -7.5, -5, 5, 7.5, 10, 12.5, 15, 17.5, 20] colormap = 'seismic' temp = tempdata.sel(time="2018-07-01", plev="3e+04") plotcorners = [-120, -30, 120, 80] plot_filled_contours_map('Monthly mean of meridional wind on 300 hPa', plotcorners, temp.v, levz, colormap)
问题原因
cu.add_cyclic_point会为经度数组添加循环点(重复起始经度值),导致新的经度范围超出设置的rightlon=120,而contourf绘制时会自动扩展轴范围覆盖所有数据,覆盖了之前ax.set_extent的设置。cartopymap函数中lattics固定为np.arange(0,101,10),无法适配指定的-30到80的纬度范围,导致网格线显示不符合预期。
解决方案
修改代码,在绘制等高线后重新锁定轴范围,并动态生成纬度网格线:
%matplotlib inline import matplotlib.pyplot as plt # matplotlib.pyplot ist ein Modul zum Erzeugen von Plots import numpy as np # numpy ist ein Modul zur Vereinfachung numerischer Berechnungen import xarray as xr # xarray ist das Modul zur Definition des xarray-Konstrukts import cartopy # cartopy dient zum Zeichnen von Landkarten import cartopy.crs as ccrs import cartopy.util as cu # cartopy.util wird benötigt, um ein Datenfeld zyklisch zu ergänzen, # also die erste Reihe von Werten entlang der Längengrade als letzte zu wiederholen from cartopy.mpl.gridliner import LongitudeFormatter, LatitudeFormatter # LongitudeFormatter und LatitudeFormatter werden zum Zeichnen der # Gitterlinien benötigt. import scipy.stats def cartopymap(corners): [leftlon, lowerlat, rightlon, upperlat] = corners central_lon = (leftlon+rightlon)/2 ax = plt.axes(projection=ccrs.PlateCarree()) ax.set_extent([leftlon, rightlon, lowerlat, upperlat]) ax.coastlines(resolution='110m', linewidth=1.0) lontics = np.arange(leftlon-10,rightlon,20) # 动态生成纬度网格线,适配传入的纬度范围 lattics = np.arange(lowerlat, upperlat + 1, 10) gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=1.5, color='gray', alpha=0.5, linestyle='--') gl.top_labels = False gl.right_labels = False gl.xlabel_style = {'size': 12} gl.ylabel_style = {'size': 12} gl.xformatter = LongitudeFormatter() gl.yformatter = LatitudeFormatter() return ax def plot_filled_contours_map(title, corners, Z, levz, colormap): fig = plt.figure(facecolor='1.', figsize=[10, 5]) ax = cartopymap(corners) data, lon = cu.add_cyclic_point(Z.values, Z.lon.values) lat = Z.lat CP = ax.contourf(lon, lat, data, levz, transform=ccrs.PlateCarree(), cmap=colormap, extend='both') ax.coastlines() # 绘制后重新锁定轴范围,覆盖contourf自动扩展的范围 ax.set_extent(corners, crs=ccrs.PlateCarree()) cbar = plt.colorbar(CP, ax=ax, aspect=50, fraction=0.1) cbar.ax.tick_params(labelsize=10) plt.title(title, y=1.1, fontsize=14) ncfile = "monthly_v_2018.nc" tempdata = xr.open_dataset(ncfile) levz = [-20, -17.5, -15, -12.5, -10, -7.5, -5, 5, 7.5, 10, 12.5, 15, 17.5, 20] colormap = 'seismic' temp = tempdata.sel(time="2018-07-01", plev="3e+04") plotcorners = [-120, -30, 120, 80] plot_filled_contours_map('Monthly mean of meridional wind on 300 hPa', plotcorners, temp.v, levz, colormap)
修改说明
- 在
plot_filled_contours_map函数中,绘制完contourf后调用ax.set_extent(corners, crs=ccrs.PlateCarree()),强制锁定显示范围,避免被contourf自动扩展。 - 修改
cartopymap中的lattics生成逻辑,根据传入的corners动态计算纬度网格线,适配指定的-30到80的纬度范围。
内容的提问来源于stack exchange,提问作者Squirrel_Mainz
相关产品推荐
相关产品推荐

