Pytorch可视化_cartopy+matplotlib_绘制雷达图像

学会用python画图:

1读取天气雷达组网拼图数据(包含数据和程序),数据放大了10倍存储
2 使用cartopy绘制二维图,网站https://scitools.org.uk/cartopy/docs/latest/
3 要求带行政边界
4 线宽2,主刻度和次要刻度也为2
5 要求带颜色条,放在图的右边,颜色条上面要标出单位dBZ
6 字号18-22
7 保存为svg格式,或tiff格式(tiff格式要求dpi>=200)

工作:

1.首先要知道画一个图像所需要的步骤:

Pytorch可视化_cartopy+matplotlib_绘制雷达图像_第1张图片
参考链接:气象绘图基本操作

2.根据要求分析自己要做的工作
(1)用matplotlib创建一个子图
(2)用cartopy投影出2维地图
(3)下载相关的.shp/,dat文件(国内行政划分需要的文件)
(4)在投影里添加海岸线、国界、河流、湖泊、省界(省界由上一步下载的文件得出的)等元素
(5)设置子图内投影的经纬度范围
(6)添加经纬度坐标
(7)将雷达数据覆盖到图中
(8)设置雷达数据的色度条
(9)添加南海诸岛的子图
(10)显示图片

3.详细步骤:
(1)用matplotlib创建一个子图
(2)用cartopy投影出2维地图

    proj = ccrs.PlateCarree()           #创建投影,选择cartopy的platecarree投影
    fig = plt.figure(figsize=(21,31))   #创建页面,可以自己选择大小

    ax = fig.subplots(1, 1, subplot_kw={
     'projection': proj})    #创建子图
    ax.outline_patch.set_linewidth(2)                           #设置子图边框的linewidth
    ax.set_title('天气雷达组网拼图', fontsize=22, color='k',fontproperties=font_set)#设置title

(3)下载相关的.shp/,dat文件(国内行政划分需要的文件)
注:这里dat文件我已经下载放在了同一级文件夹下,直接打开读取数据即可。没有的需要自行去下载,网上搜一下会有资料。

    #读取dat文件
    with open(r'CN-border-La.dat') as src:
        context = ''.join([line for line in src if not line.startswith('#')])
        blocks = [cnt for cnt in context.split('>') if len(cnt) > 0]
        borders = [np.fromstring(block, dtype=float, sep=' ') for block in blocks]

(4)在投影里添加海岸线、国界、河流、湖泊、省界(省界由上一步下载的文件得出的)等元素

    #添加cartopy中的国界、海岸线、河流、湖泊
    ax.add_feature(cfeat.BORDERS.with_scale('50m'), linewidth=2, zorder=1)
    ax.add_feature(cfeat.COASTLINE.with_scale('50m'), linewidth=2,zorder=1)
    ax.add_feature(cfeat.RIVERS.with_scale('50m'), linewidth=2,zorder=1)
    ax.add_feature(cfeat.LAKES.with_scale('50m'), zorder=1)
    #添加中国行政边界、十段线
    for line in borders:
        ax.plot(line[0::2], line[1::2], '-', lw=2, color='k', alpha=0.9,transform=ccrs.Geodetic())

(5)设置子图内投影的经纬度范围

    #设置子图内投影的经纬度范围
    ax.set_extent([73.0, 135.0, 12.2, 54.2])

(6)添加经纬度坐标
这里运用网格线的方式添加坐标,不过网格线的linewidth设置为0,则只显示坐标。

    #经纬度网格线设置,这里linewidth=0把网格线去掉,只保留经纬度坐标
    gl = ax.gridlines(crs=ccrs.PlateCarree(),draw_labels=True,
    linewidth=0, color='k', alpha=0.5, linestyle='--')
    gl.top_labels = False  #关闭顶端标签
    gl.right_labels = False  #关闭右侧标签
    gl.xformatter = LONGITUDE_FORMATTER  #x轴设为经度格式
    gl.yformatter = LATITUDE_FORMATTER  #y轴设为纬度格式
    #设置坐标的字号
    gl.xlabel_style = {
     'fontsize':18}
    gl.ylabel_style = {
     'fontsize':18}

(7)将雷达数据覆盖到图中

    color_max = int(ref['data_arr'].max())+1
    color_min = 0
    n_gap = 5
    levels = np.arange(color_min,color_max+10,n_gap)

    #设置雷达反射率图覆盖范围
    X = np.linspace(ref['llon'], ref['ulon'], 6200)
    Y = np.linspace(ref['llat'], ref['ulat'], 4200)
    X, Y = np.meshgrid(X, Y)
    cb = plt.contourf( X, Y,ref['data_arr'],levels=levels,cmap='jet')

(8)设置雷达数据的色度条
注:这里色度条的大小,位置设置还没有完全学会,后面会了的话来修改。

    #设置colorbar 左 下 宽 高
    l = 0.86
    b = 0.23
    w = 0.025
    h = 0.55
    #对应 l,b,w,h;设置colorbar位置;
    rect = [l,b,w,h]
    cbar_ax = fig.add_axes(rect)
    cbar = plt.colorbar( cax=cbar_ax)

    #重新设置色度条的显示间隔
    cbar.set_ticks(np.arange(color_min,color_max+10,n_gap))
    cbar.outline.set_linewidth(2)      #设置色度条边框linewidth
    cbar.ax.tick_params(labelsize=18)  #设置色度条字体大小。
    cbar.set_label("dBZ",fontsize=18)  #设置色度条单位

(9)添加南海诸岛的子图
注:南海诸岛的设置与以上设置流程大致相同,是否可以用同一文件的行政界限进行设置,我还没做,感觉可以用上面读出来的数据再显示一个图层贴上去。有空再做。

    # --设置南海子图
    # --设置地图属性,读取shp文件
    shp_path = 'cn_shp3641/'
    provinces = cfeat.ShapelyFeature(
        Reader(shp_path + 'Province_9.shp').geometries(),
        proj, edgecolor='k',
        facecolor='none'
    )

    #设置南海子图的坐标
    left, bottom, width, height = 0.67, 0.14, 0.21, 0.23
    ax2 = fig.add_axes(
        [left, bottom, width, height],
        projection=proj
    )

    #添加南海子图的详细内容
    ax2.add_feature(provinces, linewidth=2,alpha=0.9, zorder=1)
    ax2.add_feature(cfeat.COASTLINE.with_scale('50m'), linewidth=2,zorder=1)    #加载分辨率为50的海岸线
    ax2.add_feature(cfeat.RIVERS.with_scale('50m'), linewidth=2,zorder=1)       #加载分辨率为50的河流
    ax2.add_feature(cfeat.LAKES.with_scale('50m'), zorder=1)                    #加载分辨率为50的湖泊

    #设置南海子图的坐标范围,和边框linewidth
    ax2.set_extent([105, 125, 0, 25])
    ax2.outline_patch.set_linewidth(2)

(10)显示图片

    plt.show()

附上完整代码,有需要的可以参考,但具体的数据文件、行政边界文件需要自己寻找。


#加载所需包

import math
import time
import cartopy.crs as ccrs
import cartopy.feature as cfeat
from cartopy.mpl.gridliner import LATITUDE_FORMATTER, LONGITUDE_FORMATTER
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
from cartopy.io.shapereader import Reader, natural_earth
#导入数据处理模块
from mosaic_parse import MosaicParser

#设置title的中文字体
font_set = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=22)

#绘图函数
def plot_ref(ref):

    proj = ccrs.PlateCarree()           #创建投影,选择cartopy的platecarree投影
    fig = plt.figure(figsize=(21,31))   #创建页面,可以自己选择大小

    ax = fig.subplots(1, 1, subplot_kw={
     'projection': proj})    #创建子图
    ax.outline_patch.set_linewidth(2)                           #设置子图边框的linewidth
    ax.set_title('天气雷达组网拼图', fontsize=22, color='k',fontproperties=font_set)#设置title

    #读取dat文件
    with open(r'CN-border-La.dat') as src:
        context = ''.join([line for line in src if not line.startswith('#')])
        blocks = [cnt for cnt in context.split('>') if len(cnt) > 0]
        borders = [np.fromstring(block, dtype=float, sep=' ') for block in blocks]

    #添加cartopy中的国界、海岸线、河流、湖泊
    ax.add_feature(cfeat.BORDERS.with_scale('50m'), linewidth=2, zorder=1)
    ax.add_feature(cfeat.COASTLINE.with_scale('50m'), linewidth=2,zorder=1)
    ax.add_feature(cfeat.RIVERS.with_scale('50m'), linewidth=2,zorder=1)
    ax.add_feature(cfeat.LAKES.with_scale('50m'), zorder=1)
    #添加中国行政边界、十段线
    for line in borders:
        ax.plot(line[0::2], line[1::2], '-', lw=2, color='k', alpha=0.9,transform=ccrs.Geodetic())

    #设置子图内投影的经纬度范围
    ax.set_extent([73.0, 135.0, 12.2, 54.2])

    #经纬度网格线设置,这里linewidth=0把网格线去掉,只保留经纬度坐标
    gl = ax.gridlines(crs=ccrs.PlateCarree(),draw_labels=True,
    linewidth=0, color='k', alpha=0.5, linestyle='--')
    gl.top_labels = False  #关闭顶端标签
    gl.right_labels = False  #关闭右侧标签
    gl.xformatter = LONGITUDE_FORMATTER  #x轴设为经度格式
    gl.yformatter = LATITUDE_FORMATTER  #y轴设为纬度格式
    #设置坐标的字号
    gl.xlabel_style = {
     'fontsize':18}
    gl.ylabel_style = {
     'fontsize':18}

    #colorbar设置

    #设置色标的取值范围
    color_max = int(ref['data_arr'].max())+1
    color_min = 0
    n_gap = 5
    levels = np.arange(color_min,color_max+10,n_gap)

    #设置雷达反射率图覆盖范围
    X = np.linspace(ref['llon'], ref['ulon'], 6200)
    Y = np.linspace(ref['llat'], ref['ulat'], 4200)
    X, Y = np.meshgrid(X, Y)
    cb = plt.contourf( X, Y,ref['data_arr'],levels=levels,cmap='jet')

    #设置colorbar 左 下 宽 高
    l = 0.86
    b = 0.23
    w = 0.025
    h = 0.55
    #对应 l,b,w,h;设置colorbar位置;
    rect = [l,b,w,h]
    cbar_ax = fig.add_axes(rect)
    cbar = plt.colorbar( cax=cbar_ax)

    #重新设置色度条的显示间隔
    cbar.set_ticks(np.arange(color_min,color_max+10,n_gap))
    cbar.outline.set_linewidth(2)      #设置色度条边框linewidth
    cbar.ax.tick_params(labelsize=18)  #设置色度条字体大小。
    cbar.set_label("dBZ",fontsize=18)  #设置色度条单位


    # --设置南海子图
    # --设置地图属性,读取shp文件
    shp_path = 'cn_shp3641/'
    provinces = cfeat.ShapelyFeature(
        Reader(shp_path + 'Province_9.shp').geometries(),
        proj, edgecolor='k',
        facecolor='none'
    )

    #设置南海子图的坐标
    left, bottom, width, height = 0.67, 0.14, 0.21, 0.23
    ax2 = fig.add_axes(
        [left, bottom, width, height],
        projection=proj
    )

    #添加南海子图的详细内容
    ax2.add_feature(provinces, linewidth=2,alpha=0.9, zorder=1)
    ax2.add_feature(cfeat.COASTLINE.with_scale('50m'), linewidth=2,zorder=1)    #加载分辨率为50的海岸线
    ax2.add_feature(cfeat.RIVERS.with_scale('50m'), linewidth=2,zorder=1)       #加载分辨率为50的河流
    ax2.add_feature(cfeat.LAKES.with_scale('50m'), zorder=1)                    #加载分辨率为50的湖泊

    #设置南海子图的坐标范围,和边框linewidth
    ax2.set_extent([105, 125, 0, 25])
    ax2.outline_patch.set_linewidth(2)

    #保存
    #plt.savefig('./全国雷达组网拼图.png')
    #plt.savefig('./全国雷达组网拼图.tiff',dip=300)  # 指定分辨率保存
    plt.show()


numBlock = 0

#读取数据文件
filename = r'.\ACHN_CREF_20190720_140000.bin'
f = open(filename, 'rb')
buf = f.read()
print(len(buf))
f.close()

#解压数据
radar_parser = MosaicParser()
ref = radar_parser.parse(buf)

plot_ref(ref)

图像:
南海诸岛子图的位置有空的时候再调一下。
Pytorch可视化_cartopy+matplotlib_绘制雷达图像_第2张图片

你可能感兴趣的:(数据处理,python,可视化,数据可视化,matplotlib)