gpt4 book ai didi

python - 颜色条相对于地理轴的正确放置(cartopy)

转载 作者:太空狗 更新时间:2023-10-29 16:55:45 25 4
gpt4 key购买 nike

使用 Cartopy,我想完全控制颜色条的去向。通常我通过获取当前轴位置作为基础然后为颜色条创建新轴来做到这一点。这适用于标准 matplotlib 轴,但在使用 Cartopy 和 geo_axes 时效果不佳,因为这会扭曲轴。

所以,我的问题是:如何获得 geo_axes 的准确位置?

这是一个基于 Cartopy 文档的代码示例 http://scitools.org.uk/cartopy/docs/latest/matplotlib/advanced_plotting.html :

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import os
from netCDF4 import Dataset as netcdf_dataset
from cartopy import config

def main():
fname = os.path.join(config["repo_data_dir"],
'netcdf', 'HadISST1_SST_update.nc'
)

dataset = netcdf_dataset(fname)

sst = dataset.variables['sst'][0, :, :]
lats = dataset.variables['lat'][:]
lons = dataset.variables['lon'][:]

#my preferred way of creating plots (even if it is only one plot)
ef, ax = plt.subplots(1,1,figsize=(10,5),subplot_kw={'projection': ccrs.PlateCarree()})
ef.subplots_adjust(hspace=0,wspace=0,top=0.925,left=0.1)

#get size and extent of axes:
axpos = ax.get_position()
pos_x = axpos.x0+axpos.width + 0.01# + 0.25*axpos.width
pos_y = axpos.y0
cax_width = 0.04
cax_height = axpos.height
#create new axes where the colorbar should go.
#it should be next to the original axes and have the same height!
pos_cax = ef.add_axes([pos_x,pos_y,cax_width,cax_height])

im = ax.contourf(lons, lats, sst, 60, transform=ccrs.PlateCarree())

ax.coastlines()

plt.colorbar(im, cax=pos_cax)

ax.coastlines(resolution='110m')
ax.gridlines()
ax.set_extent([-20, 60, 33, 63])

#when using this line the positioning of the colorbar is correct,
#but the image gets distorted.
#when omitting this line, the positioning of the colorbar is wrong,
#but the image is well represented (not distorted).
ax.set_aspect('auto', adjustable=None)

plt.savefig('sst_aspect.png')
plt.close()



if __name__ == '__main__': main()

结果图,当使用“set_aspect”时: enter image description here

结果图,当省略“set_aspect”时: enter image description here

基本上,我想获得第一个数字(正确放置的颜色条)但不使用“set_aspect”。我想这应该可以通过一些转换来实现,但到目前为止我还没有找到解决方案。

谢谢!

最佳答案

好问题!感谢您提供代码和图片,它使问题更容易理解,也更容易快速迭代可能的解决方案。

这里的问题本质上是一个 matplotlib 问题。 Cartopy 调用 ax.set_aspect('equal'),因为这是投影定义的笛卡尔单位的一部分。

Matplotlib 的等纵横比功能会调整轴的大小以匹配 x 和 y 限制,而不是更改限制以适合轴矩形。正是由于这个原因,轴没有填充图中分配给它的空间。如果您以交互方式调整图形大小,您会看到轴占据的空间量根据您将图形大小调整到的方向而变化。

识别轴位置的最简单方法是使用您已经使用过的 ax.get_position() 方法。然而,正如我们现在所知,这个“位置”随着图形的大小而变化。因此,一种解决方案是每次调整图形大小时重新计算颜色条的位置。

matplotlib event machinery有一个“resize_event”,每次调整图形大小时都会触发。如果我们将这种机器用于您的颜色条,我们的事件可能看起来像:

def resize_colobar(event):
# Tell matplotlib to re-draw everything, so that we can get
# the correct location from get_position.
plt.draw()

posn = ax.get_position()
colorbar_ax.set_position([posn.x0 + posn.width + 0.01, posn.y0,
0.04, axpos.height])

fig.canvas.mpl_connect('resize_event', resize_colobar)

因此,如果我们将此与 cartopy 和您最初的问题联系起来,现在可以根据地理轴的位置调整颜色条的大小。执行此操作的完整代码可能如下所示:

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import os
from netCDF4 import Dataset as netcdf_dataset
from cartopy import config


fname = os.path.join(config["repo_data_dir"],
'netcdf', 'HadISST1_SST_update.nc'
)
dataset = netcdf_dataset(fname)
sst = dataset.variables['sst'][0, :, :]
lats = dataset.variables['lat'][:]
lons = dataset.variables['lon'][:]

fig, ax = plt.subplots(1, 1, figsize=(10,5),
subplot_kw={'projection': ccrs.PlateCarree()})

# Add the colorbar axes anywhere in the figure. Its position will be
# re-calculated at each figure resize.
cbar_ax = fig.add_axes([0, 0, 0.1, 0.1])

fig.subplots_adjust(hspace=0, wspace=0, top=0.925, left=0.1)

sst_contour = ax.contourf(lons, lats, sst, 60, transform=ccrs.PlateCarree())


def resize_colobar(event):
plt.draw()

posn = ax.get_position()
cbar_ax.set_position([posn.x0 + posn.width + 0.01, posn.y0,
0.04, posn.height])

fig.canvas.mpl_connect('resize_event', resize_colobar)

ax.coastlines()

plt.colorbar(sst_contour, cax=cbar_ax)


ax.gridlines()
ax.set_extent([-20, 60, 33, 63])

plt.show()

关于python - 颜色条相对于地理轴的正确放置(cartopy),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30030328/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com