编程语言
首页 > 编程语言> > python – 相对于地理轴(cartopy)正确放置colorbar

python – 相对于地理轴(cartopy)正确放置colorbar

作者:互联网

使用Cartopy,我想完全控制我的colorbar去哪里.通常我通过将当前轴位置作为基础然后为颜色条创建新轴来实现此目的.这适用于标准matplotlib轴,但不适用于使用Cartopy和geo_axes时,因为这会扭曲轴.

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

以下是基于Cartopy docs 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”时:

结果图,省略“set_aspect”时:

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

谢谢!

解决方法:

好问题!感谢代码和图片,它使问题更容易理解,并且更容易快速迭代可能的解决方案.

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

Matplotlib的等长宽比功能调整轴的大小以匹配x和y限制,而不是更改限制以适合轴矩形.正是由于这个原因,轴没有填充图中分配给它的空间.如果以交互方式调整图形大小,您将看到轴占用的空间量取决于您调整图形的方面.

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

matplotlib event machinery有一个“resize_event”,每次调整一个数字时都会触发它.如果我们将此机器用于您的colorbar,我们的活动可能如下所示:

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)

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

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

标签:colorbar,cartopy,axes,python,matplotlib
来源: https://codeday.me/bug/20191006/1859326.html