爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 54380|回复: 30

[源代码] Python绘制全球地形和中国地形

  [复制链接]

新浪微博达人勋

发表于 2020-4-22 16:10:29 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
本帖最后由 Masterpiece 于 2020-5-10 22:44 编辑

全球地形
程序中包含有matplotlib+basemap绘制contourf的基础操作,以及截取(truncate)部分官方色表(colormap)的做法,同时还有
当contourf中设置extend='both'之后,重新定义低出绘制区间数据所使用的颜色的做法(set_under)
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from mpl_toolkits.basemap import Basemap
  4. import netCDF4 as nc
  5. import matplotlib as mpl

  6. def truncate_colormap(cmap, minval=0.0, maxval=1.0, n=128):
  7.     new_cmap = mpl.colors.LinearSegmentedColormap.from_list('trunc({n},{a:.2f},{b:.2f})'.format(n=cmap.name,a=minval, b=maxval),cmap(np.linspace(minval, maxval, n)))
  8.     return new_cmap

  9. topo_file='ETOPO2v2g_f4.nc'
  10. data=nc.Dataset(topo_file)
  11. topo=data.variables['z'][:,:]
  12. lat=data.variables['y'][:]
  13. lon=data.variables['x'][:]

  14. lon_leftup=-180;lat_leftup=90
  15. lon_rightdown=180;lat_rightdown=-90 #建立地图投影

  16. fig, ax = plt.subplots(figsize=(14,9)) #建立绘图平台
  17. m = Basemap(projection='cyl', llcrnrlat=lat_rightdown, urcrnrlat=lat_leftup, llcrnrlon=lon_leftup, urcrnrlon=lon_rightdown, resolution='i')
  18. m.drawcoastlines(linewidth=0.2, color='gray',zorder=3)

  19. parallels = np.arange(-90,90+30,25) #纬线
  20. m.drawparallels(parallels,labels=[True,False,False,False],linewidth=0.01,dashes=[1,400])
  21. plt.yticks(parallels,len(parallels)*[''])
  22. meridians = np.arange(-180,180+30,30) #经线
  23. m.drawmeridians(meridians,labels=[False,False,False,True],linewidth=0.01,dashes=[1,400])
  24. plt.xticks(meridians,len(meridians)*[''])

  25. lons, lats = np.meshgrid(lon,lat) #经纬度2维化
  26. x, y = m(lons, lats) #投影映射

  27. cmap_new = truncate_colormap(plt.cm.terrain, 0.23, 1.0) #截取colormap,要绿色以上的(>=0.23)
  28. cmap_new.set_under([198/255,234/255,250/255]) #低于0的填色为海蓝
  29. lev=np.arange(0,5600,200)
  30. norm3 = mpl.colors.BoundaryNorm(lev, cmap_new.N) #标准化level,映射色标
  31. cf=m.contourf(x,y,topo,levels=lev,norm=norm3
  32.               ,cmap=cmap_new,extend='both')

  33. cb=plt.colorbar(cf, ax=ax,shrink=0.7,aspect=30,pad=0.05,orientation='horizontal') #色标
  34. cb.ax.tick_params(labelsize=10,pad=2,direction='in') #色标tick

  35. plt.savefig('global_etopo.png',dpi=300,bbox_inches='tight') #存图
复制代码
global_etopo.png
中国地形+气候160站
shp文件可以在家园里边搜(bou1_4l和country1),160站的csv在下边附件。
这个程序除了上边提到的技巧之外,其中一个就是地图投影的设置,还有使用汉字的操作。
还有就是使用shape文件maskout完美白化区域的做法,这个具体请参考下边给出的原贴。
matplotlib的scatter默认设置下的多边形marker,放大细看边角是圆的,假如利用path_effects为散点添加细边框可以解决这一问题,而且会让图更好看~
南海小图是通过在主图右下角添加图轴(axes)来达成的:plt.axes([小图x位置, 小图y位置, 小图的长, 小图的高])
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from mpl_toolkits.basemap import Basemap
  4. import netCDF4 as nc
  5. import matplotlib as mpl
  6. import pandas as pd
  7. import maskout
  8. import matplotlib.patheffects as path_effects

  9. def truncate_colormap(cmap, minval=0.0, maxval=1.0, n=128):
  10.     new_cmap = mpl.colors.LinearSegmentedColormap.from_list('trunc({n},{a:.2f},{b:.2f})'.format(n=cmap.name,a=minval, b=maxval),cmap(np.linspace(minval, maxval, n)))
  11.     return new_cmap

  12. topo_file='ETOPO2v2g_f4.nc'
  13. data=nc.Dataset(topo_file)
  14. print(data)
  15. topo=data.variables['z'][2600:,5400:]
  16. lat=data.variables['y'][2600:]
  17. lon=data.variables['x'][5400:]

  18. sta = pd.read_csv('sta160.csv', header=0, names=['sname', 'sid', 'slat', 'slon'])
  19. sta_name_160 = sta['sname']
  20. sta_id_160 = sta['sid']
  21. lo_160= sta['slon'].to_numpy()
  22. la_160 = sta['slat'].to_numpy()

  23. fig, ax = plt.subplots(figsize=(11,8)) #建立绘图平台
  24. m = Basemap(width=6500000,height=4300000
  25.             ,resolution='l',projection='lcc',
  26.             lat_1=30.,lat_2=45,lat_0=36,lon_0=109.)
  27. m.readshapefile('D:\\dt\\bou1_4l', 'chn', color='k', linewidth=0.5)
  28. m.drawcoastlines(linewidth=0.3, color='gray')

  29. parallels = np.arange(0,80,10) #纬线
  30. m.drawparallels(parallels,labels=[True,False,False,False],linewidth=0.3,dashes=[1,4])
  31. meridians = np.arange(80,150,10) #经线
  32. m.drawmeridians(meridians,labels=[False,False,False,True],linewidth=0.3,dashes=[1,4])

  33. lons, lats = np.meshgrid(lon,lat) #经纬度2维化
  34. x, y = m(lons, lats) #投影映射

  35. cmap_new = truncate_colormap(plt.cm.terrain, 0.23, 1.0) #截取colormap,要绿色以上的(>=0.23)
  36. cmap_new.set_under([198/255,234/255,250/255]) #低于0的填色为海蓝
  37. lev=np.arange(0,5600,200)
  38. norm3 = mpl.colors.BoundaryNorm(lev, cmap_new.N) #标准化level,映射色标
  39. cf=m.contourf(x,y,topo,levels=lev,norm=norm3
  40.               ,cmap=cmap_new,extend='both')
  41. clip=maskout.shp2clip(cf,ax,m,'D:/dt/country1',['China'])

  42. cb=plt.colorbar(cf, ax=ax,shrink=0.7,aspect=30,pad=0.05,orientation='horizontal') #色标
  43. cb.ax.tick_params(labelsize=10,pad=2,direction='in') #色标tick

  44. aa,bb=m(lo_160, la_160)
  45. t=m.scatter(aa, bb, s=25, marker='^',label='CMA   (%d Stations)'%len(lo_160), color='g', zorder=6)
  46. t.set_path_effects([path_effects.PathPatchEffect(edgecolor='k', facecolor='r', linewidth=0.3)])
  47. ax.legend(loc=1)

  48. # 南海小图
  49. a = plt.axes([0.73, 0.27, 0.12, 0.23])
  50. lon_leftup=107;lat_leftup=24
  51. lon_rightdown=121.3;lat_rightdown=2.4
  52. m = Basemap(projection='cyl', llcrnrlat=lat_rightdown, urcrnrlat=lat_leftup, llcrnrlon=lon_leftup, urcrnrlon=lon_rightdown, resolution='l')
  53. m.drawcoastlines(linewidth=0.3, color='gray')
  54. m.readshapefile('D:\\dt\\bou1_4l', 'chn', color='k', linewidth=0.5)

  55. x, y = m(lons, lats) #投影映射
  56. cf=m.contourf(x,y,topo,levels=lev,norm=norm3
  57.               ,cmap=cmap_new,extend='both')
  58. clip2=maskout.shp2clip(cf,a,m,'D:/dt/country1',['China'])
  59. aa,bb=m(lo_160, la_160)
  60. t=m.scatter(aa, bb, s=25, marker='^',label='CMA   (%d Stations)'%len(lo_160), color='g', zorder=6)
  61. t.set_path_effects([path_effects.PathPatchEffect(edgecolor='k', facecolor='r', linewidth=0.3)])

  62. font1={'family':'SimHei','size':8,'color':'black'}
  63. a.text(0.58,0.04,'南海诸岛',transform=a.transAxes,fontdict=font1,
  64.        bbox=dict(boxstyle='square',ec='k',fc='w',pad=0.3))

  65. plt.savefig('chn_etopo160.png',dpi=300,bbox_inches='tight') #存图
  66. plt.show()
复制代码
chn_etopo160.png
---中国气候160站地理位置信息---
sta160.csv (4.23 KB, 下载次数: 116)

评分

参与人数 4金钱 +42 贡献 +4 收起 理由
油油切克闹 + 2
577777 + 5 赞一个!
mofangbao + 10 + 2
尽头的尽头 + 25 + 2 赞一个!

查看全部评分

密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2020-4-22 18:08:14 | 显示全部楼层
感谢分享~~~
密码修改失败请联系微信:mofangbao
回复

使用道具 举报

新浪微博达人勋

发表于 2020-4-22 18:44:38 | 显示全部楼层
色系不错啊!
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2020-4-22 21:48:30 | 显示全部楼层
感觉楼主分享的很不错!!!!!!!!!!!
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2020-4-23 11:24:50 | 显示全部楼层
楼主,白化的图用的是哪个maskout文件,那个帖子里面说了两个呢
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2020-4-23 14:10:16 | 显示全部楼层
sihaike007 发表于 2020-4-23 11:24
楼主,白化的图用的是哪个maskout文件,那个帖子里面说了两个呢

用2016更新的那个,提到支持不同投影的
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2020-4-24 13:23:11 | 显示全部楼层
谢谢楼主呀,大爱!
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2020-4-27 12:23:47 | 显示全部楼层
大神,在哪里下载ETOPO2v2g_f4.nc   
小白找了半天没有找到。发现一个网站,但是没有找到数据
https://grasswiki.osgeo.org/wiki ... raphy_.28GDEM_V2.29

请大神发个下载链接吧
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2020-4-27 13:27:40 | 显示全部楼层
学而不厌 发表于 2020-4-27 12:23
大神,在哪里下载ETOPO2v2g_f4.nc   
小白找了半天没有找到。发现一个网站,但是没有找到数据
https://gr ...

https://www.ngdc.noaa.gov/mgg/global/relief/ETOPO2/ETOPO2v2-2006/
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2020-5-7 11:11:45 | 显示全部楼层
楼主 我刚开始接触python 比较小白 麻烦请教一下 运行时提示这个错误 网上没查到是什么问题 是我的shp文件的问题吗 微信截图_20200507110947.png
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表