爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 591|回复: 0

[源代码] GPM 卫星IMERG降水数据的简单可视化

[复制链接]

新浪微博达人勋

发表于 2024-6-5 16:55:54 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 tosaka 于 2024-6-5 16:55 编辑

公众号:气python风雨
和鲸在线运行链接:GPM卫星简单可视化 - Heywhale.com
GPM IMERG的简单可视化
GPM数据之前写了下载教程,现在简单试试可视化,毕竟是nc格式数据(下载可选),用起来相对简单


1.1 导入库与查看数据

  1. # 导入库
  2. import numpy as np
  3. import xarray as xr
  4. #可视化
  5. import matplotlib.pyplot as plt
  6. import cartopy.crs as ccrs
  7. import cartopy.feature as cfeat
  8. import cartopy.io.shapereader as shpreader
  9. from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
  10. import cmaps
  11. from shapely import geometry as sgeom
  12. # 辅助模块
  13. from glob import glob
  14. from copy import copy
复制代码
  1. # 读取
  2. ds = xr.open_dataset('/home/mw/input/GPM5633/gpmPython/3B-DAY.MS.MRG.3IMERG.20210519-S000000-E235959.V06.nc4')
  3. print(ds)
复制代码


                               
登录/注册后可看大图



可见该数据为2021年5月19日的日降水数据,经纬度分辨率为0.1°
ProductionTime指的是产品生成时间,因为这是三级数据,在三个月后生成是正常的。具体可见官网解释产品分级。


1.2 IMERG降水可视化
加入修正cartopy无法正常显示经纬度的函数

  1. '''
  2. 参考Andrew Dawson 提供的解决方法: https://gist.github.com/ajdawson/dd536f786741e987ae4e
  3. '''
  4. # 给出一个假定为矩形的LineString,返回对应于矩形给定边的直线。
  5. def find_side(ls, side):
  6.     """
  7.     Given a shapely LineString which is assumed to be rectangular, return the
  8.     line corresponding to a given side of the rectangle.
  9.     """
  10.     minx, miny, maxx, maxy = ls.bounds
  11.     points = {'left': [(minx, miny), (minx, maxy)],
  12.               'right': [(maxx, miny), (maxx, maxy)],
  13.               'bottom': [(minx, miny), (maxx, miny)],
  14.               'top': [(minx, maxy), (maxx, maxy)],}
  15.     return sgeom.LineString(points[side])

  16. # 在兰伯特投影的底部X轴上绘制刻度线
  17. def lambert_xticks(ax, ticks):
  18.     """Draw ticks on the bottom x-axis of a Lambert Conformal projection."""
  19.     te = lambda xy: xy[0]
  20.     lc = lambda t, n, b: np.vstack((np.zeros(n) + t, np.linspace(b[2], b[3], n))).T
  21.     xticks, xticklabels = _lambert_ticks(ax, ticks, 'bottom', lc, te)
  22.     ax.xaxis.tick_bottom()
  23.     ax.set_xticks(xticks)
  24.     ax.set_xticklabels([ax.xaxis.get_major_formatter()(xtick) for xtick in xticklabels])

  25. # 在兰伯特投影的左侧y轴上绘制刻度线
  26. def lambert_yticks(ax, ticks):
  27.     """Draw ricks on the left y-axis of a Lamber Conformal projection."""
  28.     te = lambda xy: xy[1]
  29.     lc = lambda t, n, b: np.vstack((np.linspace(b[0], b[1], n), np.zeros(n) + t)).T
  30.     yticks, yticklabels = _lambert_ticks(ax, ticks, 'left', lc, te)
  31.     ax.yaxis.tick_left()
  32.     ax.set_yticks(yticks)
  33.     ax.set_yticklabels([ax.yaxis.get_major_formatter()(ytick) for ytick in yticklabels])

  34. # 获取兰伯特投影中底部X轴或左侧y轴的刻度线位置和标签
  35. def _lambert_ticks(ax, ticks, tick_location, line_constructor, tick_extractor):
  36.     """Get the tick locations and labels for an axis of a Lambert Conformal projection."""
  37.     outline_patch = sgeom.LineString(ax.outline_patch.get_path().vertices.tolist())
  38.     axis = find_side(outline_patch, tick_location)
  39.     n_steps = 30
  40.     extent = ax.get_extent(ccrs.PlateCarree())
  41.     _ticks = []
  42.     for t in ticks:
  43.         xy = line_constructor(t, n_steps, extent)
  44.         proj_xyz = ax.projection.transform_points(ccrs.Geodetic(), xy[:, 0], xy[:, 1])
  45.         xyt = proj_xyz[..., :2]
  46.         ls = sgeom.LineString(xyt.tolist())
  47.         locs = axis.intersection(ls)
  48.         if not locs:
  49.             tick = [None]
  50.         else:
  51.             tick = tick_extractor(locs.xy)
  52.         _ticks.append(tick[0])
  53.     # Remove ticks that aren't visible:
  54.     ticklabels = copy(ticks)
  55.     while True:
  56.         try:
  57.             index = _ticks.index(None)
  58.         except ValueError:
  59.             break
  60.         _ticks.pop(index)
  61.         ticklabels.pop(index)
  62.     return _ticks, ticklabels
复制代码
ps: 需要使用np.transpose()进行倒转维度,不然画不出来
  1. #precipitationcal是指质控的降水数据
  2. prep=ds.precipitationCal
  3. lon=prep.lon
  4. lat=prep.lat
  5. prep=prep[0,:,:].transpose()
  6. lon, lat = np.meshgrid(lon, lat)
  7. # 设置地图投影和范围
  8. proj = ccrs.LambertConformal(central_longitude=105, central_latitude=90, standard_parallels=(25, 47))
  9. extent = [80, 130, 17, 55]

  10. # 创建画布和子图
  11. fig, ax = plt.subplots(figsize=(10,5), subplot_kw={'projection': proj})

  12. # 设置网格点属性
  13. #gl = ax.gridlines(draw_labels=True, alpha=0.5, linewidth=1, color='k', linestyle='--')
  14. #gl.xlabels_top = False  # 关闭顶端标签
  15. #gl.ylabels_right = False  # 关闭右侧标签
  16. #gl.xformatter = LONGITUDE_FORMATTER  # x轴设为经度格式
  17. #gl.yformatter = LATITUDE_FORMATTER  # y轴设为纬度格式
  18. # 绘制降水数据,设置colorbar
  19. levels = np.arange(0, 50, 2)
  20. cf = ax.pcolormesh(lon, lat, prep, cmap=cmaps.WhiteBlue, vmin=0, vmax=50, transform=ccrs.PlateCarree())
  21. plt.title('gpm precipitation at 20220903(UTC)', fontsize=12)

  22. # 添加经纬度网格线
  23. ax.gridlines(color='black', linestyle='dotted')

  24. # 添加经纬度标签
  25. xticks = list(np.arange(80,130,5))
  26. yticks = list(np.arange(17,55,5))
  27. fig.canvas.draw()
  28. ax.xaxis.set_major_formatter(LONGITUDE_FORMATTER)
  29. ax.yaxis.set_major_formatter(LATITUDE_FORMATTER)
  30. lambert_xticks(ax, xticks)
  31. lambert_yticks(ax, yticks)

  32. # 添加colorbar
  33. cbar_ax = fig.add_axes([0.80, 0.12, 0.02, 0.8])
  34. cb = plt.colorbar(cf, cax=cbar_ax, ticks=levels)
  35. cb.set_label('Total Precipitaion (mm)', fontdict={'size':10})
  36. cb.ax.tick_params(labelsize=10)
  37. # 添加省界数据
  38. province = shpreader.Reader('/home/mw/project/cnhimap.shp')
  39. ax.add_geometries(province.geometries(), crs=ccrs.PlateCarree(), linewidths=0.5, edgecolor='k', facecolor='none')
  40. # 设置地图范围和显示
  41. ax.set_extent(extent, crs=ccrs.PlateCarree())
  42. plt.show()
复制代码

                               
登录/注册后可看大图

1.3 GMI(hdf5)¶
  1. # 读取GPM GMI降水产品
  2. import numpy as np
  3. import h5py                  
  4. import matplotlib.pyplot as plt
  5. import cartopy.crs as ccrs
  6. import warnings
  7. warnings.filterwarnings("ignore")
  8. file = '/home/mw/input/GPM5633/gpmPython/2A.GPM.GMI.GPROF.20210829-S151345-E151504.042624.V05B.subset.HDF5'
  9. f = h5py.File(file,"r")
  10. print(f['S1'].keys())
  11. prns = f['/S1/surfacePrecipitation']
  12. lon  = np.array(f["/S1/Longitude"])
  13. lat  = np.array(f["/S1/Latitude"])
  14. print('precipRate dimension sizes are:',prns.shape)

  15. prnsdata = np.ndarray(shape=prns.shape,dtype=float)
  16. prns.read_direct(prnsdata)
  17. prnsdata[prnsdata <= -9999] = np.nan

  18. start = 0
  19. end = 43
  20. mysub = prnsdata[start:end,:]
  21. mylon = lon[start:end,:]
  22. mylat = lat[start:end,:]
  23. prnsdata.min()

  24. # Draw the subset of near-surface precipitation rate
  25. fig = plt.figure(figsize=(8, 8))
  26. ax = plt.axes(projection=ccrs.PlateCarree())
  27. plt.title('test')
  28. # Add coastlines and gridlines
  29. ax.coastlines(resolution="50m",linewidth=0.5)
  30. gl = ax.gridlines(crs=ccrs.PlateCarree(),draw_labels=True,
  31.                   linewidth=0.8,color='#555555',alpha=0.5,linestyle='--')
  32. # Axis labels
  33. gl.xlabels_top = False
  34. gl.ylabels_right = False
  35. gl.xlines = True

  36. # Plot the scatter diagram
  37. pp = plt.scatter(mylon, mylat, c=mysub, cmap=cmap_Rr, transform=ccrs.PlateCarree())

  38. # Add a colorbar to the bottom of the plot.
  39. fig.subplots_adjust(bottom=0.15,left=0.06,right=0.94)
  40. cbar_ax = fig.add_axes([0.12, 0.08, 0.76, 0.025])  
  41. cbar = plt.colorbar(pp,cax=cbar_ax,orientation='horizontal')

复制代码

                               
登录/注册后可看大图

1.4 GMI可视化nc版
  1. ds1 = xr.open_dataset('/home/mw/project/2A.GPM.GMI.GPROF2021v1.20220902-S223342-E000616.048370.V07A.HDF5.nc4')
  2. print(ds1)
  3. #看文件描述的近地面降水 GMI
  4. from pathlib import Path
  5. from collections import namedtuple

  6. import h5py
  7. import numpy as np
  8. import matplotlib.pyplot as plt
  9. import matplotlib.ticker as mticker
  10. import matplotlib.cm as cm
  11. import matplotlib.colors as mcolors
  12. import cmaps
  13. import cartopy.crs as ccrs
  14. import cartopy.feature as cfeature
  15. from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter

  16. def make_Rr_cmap(levels):
  17.     '''制作降水的colormap.'''
  18.     nbin = len(levels) - 1
  19.     cmap = cm.get_cmap('jet', nbin)
  20.     norm = mcolors.BoundaryNorm(levels, nbin)

  21.     return cmap, norm

  22. def region_mask(lon, lat, extents):
  23.     '''返回用于索引经纬度方框内数据的Boolean数组.'''
  24.     lonmin, lonmax, latmin, latmax = extent
  25.     return (
  26.         (lon >= lonmin) & (lon <= lonmax) &
  27.         (lat >= latmin) & (lat <= latmax)
  28.     )

  29. extent = [80, 130, 17, 55]
  30. surfacePrecipitation = ds1.S1_surfacePrecipitation
  31. lon=surfacePrecipitation.S1_Longitude
  32. lat=surfacePrecipitation.S1_Latitude
  33. #prep=prep[0,:,:].transpose()
  34. levels_Rr = [0.1, 0.5, 1.0, 2.0, 3.0, 5.0, 10.0, 15.0, 20.0, 25, 30]

  35. cmap_Rr,norm_Rr = make_Rr_cmap(levels_Rr)
  36. #cmap_LH, norm_LH = make_LH_cmap(levels_LH)

  37. #lon, lat = np.meshgrid(lon, lat)
  38. nscan, npixel = lon.shape
  39. midpixel = npixel // 2
  40. mask = region_mask(lon[:, midpixel], lat[:, midpixel], extent)
  41. index = np.s_[mask, :]
  42. lon = lon[index]
  43. lat = lat[index]
  44. surfacePrecipitation = surfacePrecipitation[index]
  45.     # 画出GMI降水.

  46. proj = ccrs.PlateCarree()
  47. fig = plt.figure(figsize=(10, 8))
  48. ax = fig.add_subplot(111, projection=proj)
  49. ax.coastlines(resolution='50m', lw=0.5)
  50. ax.add_feature(cfeature.OCEAN.with_scale('50m'))
  51. ax.add_feature(cfeature.LAND.with_scale('50m'))
  52. ax.set_xticks(np.arange(-180, 181, 5), crs=proj)
  53. ax.set_yticks(np.arange(-90, 91, 5), crs=proj)
  54. ax.xaxis.set_minor_locator(mticker.AutoMinorLocator(2))
  55. ax.yaxis.set_minor_locator(mticker.AutoMinorLocator(2))
  56. ax.xaxis.set_major_formatter(LongitudeFormatter())
  57. ax.yaxis.set_major_formatter(LatitudeFormatter())
  58. ax.set_extent(extent, crs=proj)
  59. ax.tick_params(labelsize='large')
  60. cmap_Rr.set_under(color='lavender')

  61. im = ax.contourf(
  62.     lon, lat, surfacePrecipitation, levels_Rr,
  63.     cmap=cmap_Rr, norm=norm_Rr, alpha=0.5,
  64.     extend='both', transform=proj
  65. )
  66. cbar = fig.colorbar(im, ax=ax, ticks=levels_Rr)
  67. cbar.set_label('Rain Rate (mm/hr)', fontsize='large')
  68. cbar.ax.tick_params(labelsize='large')
  69. plt.show()
复制代码

                               
登录/注册后可看大图


这画图范围是我一个个区域去试出来,感觉不太方便,不知有没更高效的方法

数据和程序都放在和鲸社区,想复现去帖子顶端的链接,Python环境问题的话自己查一下

密码修改失败请联系微信:mofangbao
您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

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

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

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