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.首先要知道画一个图像所需要的步骤:
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)