相关文章推荐
急躁的围巾  ·  Home - Canadian ...·  1 月前    · 
稳重的肉夹馍  ·  关于报考资格| 中山大学管理学院EMBA·  7 月前    · 
活泼的手套  ·  中国动画第一牛——大角牛成长记事_共产党员网·  8 月前    · 
绅士的皮蛋  ·  足球:8月8日过生日的著名球员及教练员-搜狐体育·  10 月前    · 
谦和的乌冬面  ·  国内反传销面临立法困局·  11 月前    · 
小百科  ›  选用 Basemap 和 Cartopy 绘制子图实例-腾讯云开发者社区-腾讯云
帅呆的黑框眼镜
1 年前
bugsuse
0 篇文章

使用 Basemap 和 Cartopy 绘制子图实例

前往专栏
腾讯云
开发者社区
文档 意见反馈 控制台
首页
学习
活动
专区
工具
TVP
最新优惠活动
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
bugsuse
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
社区首页 > 专栏 > 气象杂货铺 > 使用 Basemap 和 Cartopy 绘制子图实例

使用 Basemap 和 Cartopy 绘制子图实例

作者头像
bugsuse
发布 于 2020-04-20 13:46:08
2.5K 0
发布 于 2020-04-20 13:46:08
举报

平时绘制地图时,经常会将多个图放到同一个 figure 中,而这些图的地图范围通常是相同的,所以可以设置共享 x-y 轴。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from matplotlib import cm,colors
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import numpy as np
import netCDF4 as nc
fip = "F:\\"
fin1 = "wrfout_v2_Lambert.nc"
ti = [6,7,8,9]
xs = 0;   xe = -1
ys = 0;   ye = -1
zs = 0;   ze = -1
data = nc.Dataset(fip + fin1, "r")
truelat = data.TRUELAT1
truelat = data.TRUELAT2
stalon  = data.CEN_LON
stalat  = data.CEN_LAT
fn = "Arial"
fs = 10
ld = 0.
nrows = 2
ncols = 2
def sharexy(ax, nrows, ncols, i, sharex = True, sharey = True):
    if sharex:
        if i+1 in np.arange(1, (nrows - 1)*ncols + 1):
            labelsx = [0, 0, 0, 0]
        else:
            labelsx = [0, 0, 0, 1]
    else:
        labelsx = None
    if sharey:
        if i+1 not in np.arange(1, ncols*nrows, ncols):
            labelsy = [0, 0, 0, 0]
        else:
            labelsy = [1, 0, 0, 0]
    else:
        labelsy = None
    return labelsx, labelsy
fig,axes  =  plt.subplots(nrows = nrows, ncols = ncols, subplot_kw= dict(aspect = 'auto'))
for i, ax in zip(np.arange(0, nrows*ncols), axes.flat):
    rain = data.variables["RAINC"][ti[i], xs:xe, ys:ye]
    lat  = data.variables["XLAT"][ti[i], xs:xe, ys:ye]
    lon  = data.variables["XLONG"][ti[i], xs:xe, ys:ye]
    map = Basemap(ax= ax, projection="lcc", llcrnrlon = lon[-1,0], llcrnrlat = lat[0,0],\
              urcrnrlon = lon[0,-1], urcrnrlat=lat[-1,-1], lat_0 = stalat,\
              lon_0 = stalon, resolution ="h")
    x, y = map(lon, lat)
# 添加经度,纬度坐标,海岸线,国界线
    labelsx, labelsy = sharexy(ax, nrows, ncols, i)
#  labels 参数用于控制经纬度 labels 的显示
    map.drawmeridians(np.arange(int(lon[-1,0]), int(lon[0,-1])+1, 2), labels = [0,0,0,1], \
                    fontname = fn, fontsize= fs, linewidth = ld, ax = ax)
    map.drawparallels(np.arange(int(lat[0,0]), int(lat[-1,-1])+1), labels = [1,0,0,0], \
                    fontname = fn, fontsize= fs, linewidth = ld, ax = ax)
    con  = map.contourf(x, y, rain)
    ax.set_adjustable('box-forced') # 防止绘图和坐标区域不一致
fig.colorbar(con, ax=axes.ravel().tolist())   
#plt.savefig("panel.eps")    
plt.show()

sharexy 函数用以设置 basemap 地图共享 x-y 轴。

未共享x-y轴

将上述语句替换为以下两句即可共享x-y轴

map.drawmeridians(np.arange(int(lon[-1,0]), int(lon[0,-1])+1, 2), labels = labelsx, \
                    fontname = fn, fontsize= fs, linewidth = ld, ax = ax)
map.drawparallels(np.arange(int(lat[0,0]), int(lat[-1,-1])+1), labels = labelsy, \
                    fontname = fn, fontsize= fs, linewidth = ld, ax = ax)

共享 x-y轴

共享 x-y 轴后,中间空白间隔太大,可以使用 subplots_adjust 方法控制

将以下语句放到 fig.colorbar 命令前一行(具有相同的缩进)

fig.subplots_adjust(top = 0.9, bottom = 0.1, left = 0.12, right = 0.77, 
                    hspace = 0.05, wspace = 0.05)                 

如果感觉 colorbar 和 panel 之间的间隔大的话, 可以设置 pad 参数并传递给 colorbar 方法。

最后说一下:一定会有人好奇,为什么不使用 subplots 的 sharex 和 sharey 参数来控制 x-y 轴共享。下面就上一张使用这种方法的图看看什么效果

可以看到并没有产生任何影响,drawmeridians 和 drawparallels 方法的 labels 参数起到了关键的作用,使 subplots 的 sharex 和 sharey 参数效果失效了。

注意:

以上图中的 colorbar 和 panel 图的对齐程度并不是很好,需要出图后再进行调整,或是直接设置 figsize 为合适的大小(但很难控制),即使传递 aspect 参数给 subplots 方法也没什么效果。而 cartopy 可以很好的解决以上遇到的问题。

下面上一张 cartopy 绘制子图的效果图

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# plot dbz-panel by WRF model data using cartopy 
from matplotlib import cm,colors
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
import netCDF4 as nc
fip = "/home/storm/python/sample_file/"
fin1 = "wrfout_v2_Lambert.nc"
ti = [6,7,8,9]
xs = 0;   xe = -1
ys = 0;   ye = -1
zs = 0;   ze = -1
data = nc.Dataset(fip + fin1, "r")
truelat1 = data.TRUELAT1
truelat2 = data.TRUELAT2
stalon  = data.CEN_LON
stalat  = data.CEN_LAT
fn = "Arial"
fs = 10
ld = 0.     
nrows = 2
ncols = 2
fig,axes  =  plt.subplots(nrows = nrows, ncols = ncols, sharex = True, sharey = True, \
    subplot_kw=dict(projection=ccrs.PlateCarree(), aspect = 'auto'))
for i, ax in zip(np.arange(0, nrows*ncols), axes.flat):
    rain  = data.variables["RAINC"][ti[i],xs:xe,ys:ye]
    lat  = data.variables["XLAT"][ti[i], xs:xe, ys:ye]
    lon  = data.variables["XLONG"][ti[i], xs:xe, ys:ye]
    ax.set_xticks(range(int(lon[-1,0]), int(lon[0,-1])+1, 2))
    ax.set_yticks(range(int(lat[0,0]), int(lat[-1,-1])+1, 1))
    lon_formatter = LongitudeFormatter(number_format='.0f',
                                       degree_symbol='',
                                       dateline_direction_label=True)
    lat_formatter = LatitudeFormatter(number_format='.0f',
                                       degree_symbol='')
    ax.xaxis.set_major_formatter(lon_formatter)
    ax.yaxis.set_major_formatter(lat_formatter)
    con = ax.contourf(lon, lat, rain)
    ax.hold(True)
    ax.coastlines(resolution = '10m')
    # 设置坐标轴范围
    ax.set_xlim([lon[-1,0], lon[0,-1]])
    ax.set_ylim([lat[0,0], lat[-1,-1]])
 
推荐文章
急躁的围巾  ·  Home - Canadian Coalition on Climate Change and Development ...
1 月前
稳重的肉夹馍  ·  关于报考资格| 中山大学管理学院EMBA
7 月前
活泼的手套  ·  中国动画第一牛——大角牛成长记事_共产党员网
8 月前
绅士的皮蛋  ·  足球:8月8日过生日的著名球员及教练员-搜狐体育
10 月前
谦和的乌冬面  ·  国内反传销面临立法困局
11 月前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
小百科 - 百科知识指南
© 2024 ~ 沪ICP备11025650号