metradar 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- metradar/__init__.py +7 -0
- metradar/cnrad_level2.py +1326 -0
- metradar/comm_func.py +135 -0
- metradar/construct_aws_refvpr_mainprog.py +515 -0
- metradar/construct_aws_refvpr_mainprog_cams.py +310 -0
- metradar/construct_aws_refvpr_mainprog_datan3d.py +386 -0
- metradar/construct_aws_refvpr_mainprog_swan.py +306 -0
- metradar/decode_fmt_pyart.py +200 -0
- metradar/decode_pup_rose.py +1993 -0
- metradar/draw_mosaic_new.py +421 -0
- metradar/draw_radar_aws_jilin_new.py +206 -0
- metradar/draw_radar_comp_func.py +1379 -0
- metradar/exceptions.py +50 -0
- metradar/geo_transforms_pyart.py +627 -0
- metradar/get_cross_section_from_pyart.py +354 -0
- metradar/get_tlogp_from_sharppy.py +93 -0
- metradar/grid.py +281 -0
- metradar/grid_data.py +64 -0
- metradar/main_pydda.py +653 -0
- metradar/make_gif.py +24 -0
- metradar/make_mosaic_mp_archive.py +538 -0
- metradar/mosaic_merge.py +64 -0
- metradar/mosaic_quickdraw.py +338 -0
- metradar/nowcast_by_pysteps.py +219 -0
- metradar/oa_couhua.py +166 -0
- metradar/oa_dig_func.py +955 -0
- metradar/parse_pal.py +148 -0
- metradar/pgmb_io.py +169 -0
- metradar/prepare_for_radar_draw.py +197 -0
- metradar/read_new_mosaic.py +33 -0
- metradar/read_new_mosaic_func.py +231 -0
- metradar/retrieve_cmadaas.py +3126 -0
- metradar/retrieve_micaps_server.py +2061 -0
- metradar/rose_structer.py +807 -0
- metradar/trans_nc_pgmb.py +62 -0
- metradar/trans_new_mosaic_nc.py +309 -0
- metradar/trans_polor2grid_func.py +203 -0
- metradar-0.1.0.dist-info/METADATA +12 -0
- metradar-0.1.0.dist-info/RECORD +41 -0
- metradar-0.1.0.dist-info/WHEEL +5 -0
- metradar-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
'''
|
|
2
|
+
将不同层次的mosacdata stack在一起
|
|
3
|
+
ZhuWJ
|
|
4
|
+
|
|
5
|
+
'''
|
|
6
|
+
|
|
7
|
+
# %%
|
|
8
|
+
import pyart
|
|
9
|
+
import os
|
|
10
|
+
import numpy as np
|
|
11
|
+
import cartopy.crs as ccrs
|
|
12
|
+
import matplotlib.pyplot as plt
|
|
13
|
+
from cartopy.io.shapereader import Reader
|
|
14
|
+
import matplotlib.patheffects as path_effects
|
|
15
|
+
from matplotlib.transforms import offset_copy
|
|
16
|
+
from matplotlib.font_manager import FontProperties
|
|
17
|
+
import pandas as pd
|
|
18
|
+
from pyart.graph import common
|
|
19
|
+
from datetime import datetime,timedelta
|
|
20
|
+
from parse_pal import parse_pro
|
|
21
|
+
import xarray as xr
|
|
22
|
+
|
|
23
|
+
def add_china_map_2cartopy(ax, name='province', facecolor='none',
|
|
24
|
+
edgecolor='c', lw=2, **kwargs):
|
|
25
|
+
"""
|
|
26
|
+
Draw china boundary on cartopy map.
|
|
27
|
+
|
|
28
|
+
:param ax: matplotlib axes instance.
|
|
29
|
+
:param name: map name.
|
|
30
|
+
:param facecolor: fill color, default is none.
|
|
31
|
+
:param edgecolor: edge color.
|
|
32
|
+
:param lw: line width.
|
|
33
|
+
:return: None
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
# map name
|
|
37
|
+
names = {'nation': "bou1_4p", 'province': "bou2_4p",
|
|
38
|
+
'county': "BOUNT_poly", 'river': "hyd1_4l",
|
|
39
|
+
'river_high': "hyd2_4l"}
|
|
40
|
+
|
|
41
|
+
# get shape filename
|
|
42
|
+
shpfile = "../common/resources/maps/" + names[name] + ".shp"
|
|
43
|
+
|
|
44
|
+
# add map
|
|
45
|
+
ax.add_geometries(
|
|
46
|
+
Reader(shpfile).geometries(), ccrs.PlateCarree(),
|
|
47
|
+
path_effects=[path_effects.Stroke(linewidth=lw+1, foreground=[0.8,0.8,0.8]),path_effects.Normal()],
|
|
48
|
+
facecolor=facecolor, edgecolor=edgecolor, lw=lw, **kwargs)
|
|
49
|
+
|
|
50
|
+
def draw_gisinfo(ax,slat,nlat,wlon,elon):
|
|
51
|
+
|
|
52
|
+
# 添加中文地名
|
|
53
|
+
|
|
54
|
+
filename = '/Users/wenjianzhu/Library/CloudStorage/OneDrive-个人/PythonCode/MyWork/nmc_met_radar/resources/中文地理信息原始文件/cma_city_station_info.xlsx'
|
|
55
|
+
|
|
56
|
+
data_guojia = pd.read_excel(filename,
|
|
57
|
+
header=0,skiprows=0,index_col=None,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
gis_lats=[]
|
|
61
|
+
gis_lons=[]
|
|
62
|
+
gis_name=[]
|
|
63
|
+
for ng in range(len(data_guojia['经度'])):
|
|
64
|
+
gis_lons.append(data_guojia['经度'][ng])
|
|
65
|
+
gis_lats.append(data_guojia['纬度'][ng])
|
|
66
|
+
gis_name.append(data_guojia['城市名'][ng])
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
fontname='/Users/wenjianzhu/Library/CloudStorage/OneDrive-个人/PythonCode/MyWork/nmc_met_radar/resources/fonts/msyhbd.ttc'
|
|
70
|
+
font2=FontProperties(fname=fontname, size=8)
|
|
71
|
+
geodetic_transform = ccrs.Geodetic()._as_mpl_transform(ax)
|
|
72
|
+
text_transform = offset_copy(geodetic_transform, units='dots', x=-5)
|
|
73
|
+
aa = (np.array(gis_lats)<nlat) & (np.array(gis_lats) > slat)
|
|
74
|
+
bb = (np.array(gis_lons)<elon) & (np.array(gis_lons) > wlon)
|
|
75
|
+
cc = aa & bb
|
|
76
|
+
# cc = cc.values
|
|
77
|
+
for nn in range(len(gis_name)):
|
|
78
|
+
if not cc[nn]:
|
|
79
|
+
continue
|
|
80
|
+
curlat = gis_lats[nn]
|
|
81
|
+
curlon = gis_lons[nn]
|
|
82
|
+
|
|
83
|
+
ax.text(curlon, curlat, gis_name[nn], clip_on=True,
|
|
84
|
+
verticalalignment='center', horizontalalignment='right',
|
|
85
|
+
transform=text_transform, fontproperties=font2, color='white',
|
|
86
|
+
path_effects=[path_effects.Stroke(linewidth=1, foreground='black'),path_effects.Normal()])
|
|
87
|
+
|
|
88
|
+
# 快速绘制垂直剖面图
|
|
89
|
+
def quick_draw_mosaic_cross(grid:pyart.core.Grid,params):
|
|
90
|
+
|
|
91
|
+
# Setting projection, figure size, and panel sizes.
|
|
92
|
+
projection = ccrs.PlateCarree()
|
|
93
|
+
|
|
94
|
+
fig = plt.figure(figsize=[16, 7])
|
|
95
|
+
|
|
96
|
+
map_panel_axes = [0.1, 0.1, .4, .80]
|
|
97
|
+
x_cut_panel_axes = [0.55, 0.15, .4, .25]
|
|
98
|
+
y_cut_panel_axes = [0.55, 0.55, .4, .25]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
# lat = 32.89
|
|
102
|
+
# lon = 118.30
|
|
103
|
+
lat = params['cross_lat']
|
|
104
|
+
lon = params['cross_lon']
|
|
105
|
+
xlim_west = params['xlim_west']
|
|
106
|
+
xlim_east = params['xlim_east']
|
|
107
|
+
ylim_south = params['ylim_south']
|
|
108
|
+
ylim_north = params['ylim_north']
|
|
109
|
+
|
|
110
|
+
xcross_left = params['xcross_left']
|
|
111
|
+
xcross_right = params['xcross_right']
|
|
112
|
+
ycross_down = params['ycross_down']
|
|
113
|
+
ycross_up = params['ycross_up']
|
|
114
|
+
zcross_bottom = params['zcross_bottom']
|
|
115
|
+
zcross_top = params['zcross_top']
|
|
116
|
+
dis_level = params['level']
|
|
117
|
+
|
|
118
|
+
min_ref = params['min_ref']
|
|
119
|
+
|
|
120
|
+
am = grid.fields['reflectivity']['data'].mask
|
|
121
|
+
da = grid.fields['reflectivity']['data'].data
|
|
122
|
+
am[da < min_ref] = True
|
|
123
|
+
|
|
124
|
+
display = pyart.graph.GridMapDisplay(grid)
|
|
125
|
+
# Set parameters.
|
|
126
|
+
level = 3
|
|
127
|
+
vmin = 0
|
|
128
|
+
vmax = 75
|
|
129
|
+
|
|
130
|
+
cmapname = 'pyart_NWSRef'
|
|
131
|
+
|
|
132
|
+
#
|
|
133
|
+
#cmapname = 'pyart_NWSVel'
|
|
134
|
+
#cmapname = 'pyart_NWS_SPW'
|
|
135
|
+
#cmapname = 'pyart_RefDiff'
|
|
136
|
+
#cmapname = 'pyart_NWS_SPW'
|
|
137
|
+
#cmapname = 'pyart_NWS_SPW'
|
|
138
|
+
|
|
139
|
+
# Panel 1: PPI plot of the second tilt.
|
|
140
|
+
ax1 = fig.add_axes(map_panel_axes, projection=projection)
|
|
141
|
+
display.plot_grid('reflectivity', dis_level, vmin=vmin, vmax=vmax,
|
|
142
|
+
ax=ax1,
|
|
143
|
+
projection=projection,
|
|
144
|
+
cmap=cmapname)
|
|
145
|
+
display.plot_crosshairs(lon=lon, lat=lat)
|
|
146
|
+
ax1.set_ylim([ylim_south, ylim_north])
|
|
147
|
+
ax1.set_xlim([xlim_west, xlim_east])
|
|
148
|
+
add_china_map_2cartopy(ax1, name='province', facecolor='none',edgecolor=None, lw=1)
|
|
149
|
+
draw_gisinfo(ax1,slat=ylim_south,nlat=ylim_north,wlon=xlim_west,elon=xlim_east)
|
|
150
|
+
# Panel 2: longitude slice
|
|
151
|
+
ax2 = fig.add_axes(x_cut_panel_axes)
|
|
152
|
+
display.plot_longitude_slice('reflectivity', lon=lon, lat=lat,
|
|
153
|
+
ax=ax2,
|
|
154
|
+
vmin=vmin, vmax=vmax,
|
|
155
|
+
cmap=cmapname)
|
|
156
|
+
|
|
157
|
+
ax2.set_ylim([zcross_bottom, zcross_top])
|
|
158
|
+
ax2.set_xlim([xcross_left, xcross_right])
|
|
159
|
+
|
|
160
|
+
# Panel 3: latitude slice
|
|
161
|
+
ax3 = fig.add_axes(y_cut_panel_axes)
|
|
162
|
+
display.plot_latitude_slice('reflectivity', lon=lon, lat=lat,
|
|
163
|
+
ax=ax3,
|
|
164
|
+
vmin=vmin, vmax=vmax,
|
|
165
|
+
cmap=cmapname)
|
|
166
|
+
ax3.set_ylim([zcross_bottom, zcross_top])
|
|
167
|
+
ax3.set_xlim([ycross_down, ycross_up])
|
|
168
|
+
plt.close()
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def draw_topo(ax=None):
|
|
173
|
+
# 读取地形数据
|
|
174
|
+
filename = '/Users/wenjianzhu/Downloads/srtm_southchina.nc'
|
|
175
|
+
topo = xr.open_dataset(filename)
|
|
176
|
+
# ax = plt.axes()
|
|
177
|
+
if ax is None:
|
|
178
|
+
ax = plt.gca()
|
|
179
|
+
ax.contour(topo['longitude'].values,topo['latitude'].values,topo['topo'],levels=[250,500,750,1000],colors='gray')
|
|
180
|
+
|
|
181
|
+
pass
|
|
182
|
+
def draw_composite_operational(gridfile,outpath='.',level=4,vmin=0,vmax=75,colorfile=None):
|
|
183
|
+
|
|
184
|
+
if not os.path.exists(gridfile):
|
|
185
|
+
print(gridfile + ' not exists!')
|
|
186
|
+
return False
|
|
187
|
+
try:
|
|
188
|
+
grid = pyart.io.read_grid(gridfile)
|
|
189
|
+
except:
|
|
190
|
+
print(gridfile + ' read error!')
|
|
191
|
+
return False
|
|
192
|
+
if not os.path.exists(outpath):
|
|
193
|
+
os.makedirs(outpath)
|
|
194
|
+
|
|
195
|
+
fontname='/Users/wenjianzhu/Library/CloudStorage/OneDrive-个人/PythonCode/MyWork/nmc_met_radar/resources/fonts/msyhbd.ttc'
|
|
196
|
+
(filepath,filename) = os.path.split(gridfile)
|
|
197
|
+
tstr = filename[7:19]
|
|
198
|
+
tt = datetime.strptime(tstr,'%Y%m%d%H%M') + timedelta(hours=8)
|
|
199
|
+
|
|
200
|
+
tstr_date = '%04d年%02d月%02d日'%(tt.year,tt.month,tt.day)
|
|
201
|
+
tstr_time = '%02d时%02d分(北京时)'%(tt.hour,tt.minute)
|
|
202
|
+
font_large=FontProperties(fname=fontname, size=14)
|
|
203
|
+
font_mid=FontProperties(fname=fontname, size=10)
|
|
204
|
+
|
|
205
|
+
min_ref=10
|
|
206
|
+
am = grid.fields['reflectivity']['data'].mask
|
|
207
|
+
da = grid.fields['reflectivity']['data'].data
|
|
208
|
+
am[da < min_ref] = True
|
|
209
|
+
xrange = grid.x['data'].max()
|
|
210
|
+
yrange = grid.y['data'].max()
|
|
211
|
+
origin_lat = grid.origin_latitude['data'][0]
|
|
212
|
+
origin_lon = grid.origin_longitude['data'][0]
|
|
213
|
+
[startlon,startlat]=pyart.core.cartesian_to_geographic_aeqd(-1*xrange,-1*yrange,origin_lon,origin_lat)
|
|
214
|
+
[endlon,endlat]=pyart.core.cartesian_to_geographic_aeqd(1*xrange,1*yrange,origin_lon,origin_lat)
|
|
215
|
+
|
|
216
|
+
display = pyart.graph.GridMapDisplay(grid)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
ax_pos_main = [0.05, 0.05, .65, .65]
|
|
220
|
+
ax_pos_top = [0.05, 0.71, .65, .2]
|
|
221
|
+
ax_pos_right = [0.71, 0.05, .2, .65]
|
|
222
|
+
ax_pos_cbar = [0.92, 0.05, .03, .65]
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
fig = plt.figure(figsize=(8,8))
|
|
226
|
+
projection = ccrs.PlateCarree()
|
|
227
|
+
ax_main = fig.add_axes(ax_pos_main, projection=projection)
|
|
228
|
+
|
|
229
|
+
fig.text(0.5,0.97, '三维雷达组网拼图-多视角组合图', va="center", ha="center", font=font_large )
|
|
230
|
+
|
|
231
|
+
# add product info
|
|
232
|
+
infostr = '要 素:' + '反射率因子'
|
|
233
|
+
fig.text(0.71,0.89, infostr, va="center", ha="left", font=font_mid )
|
|
234
|
+
infostr = '日 期:' + tstr_date
|
|
235
|
+
fig.text(0.71,0.86, infostr, va="center", ha="left", font=font_mid )
|
|
236
|
+
infostr = '时 间:' + tstr_time
|
|
237
|
+
fig.text(0.71,0.83, infostr, va="center", ha="left", font=font_mid )
|
|
238
|
+
infostr = '高 度:%d米(左下图)'%grid.z['data'][level]
|
|
239
|
+
fig.text(0.71,0.80, infostr, va="center", ha="left", font=font_mid )
|
|
240
|
+
|
|
241
|
+
ax_main.axis('tight')
|
|
242
|
+
|
|
243
|
+
xlim_west = startlon[0]
|
|
244
|
+
xlim_east = endlon[0]
|
|
245
|
+
ylim_south = startlat[0]
|
|
246
|
+
ylim_north = endlat[0]
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
field = 'reflectivity'
|
|
250
|
+
if colorfile is None:
|
|
251
|
+
cmapname = 'pyart_NWSRef'
|
|
252
|
+
cmap = common.parse_cmap(cmapname, field)
|
|
253
|
+
else:
|
|
254
|
+
# colorfile='gr2_colors/default_BR_PUP2.pal'
|
|
255
|
+
# colorfile = 'gr2_colors/BR_WDTB_Bright.pal'
|
|
256
|
+
|
|
257
|
+
outdic= parse_pro(colorfile)
|
|
258
|
+
cmap=outdic['cmap']
|
|
259
|
+
norm=outdic['norm']
|
|
260
|
+
|
|
261
|
+
display.plot_grid(field, level, vmin=vmin, vmax=vmax,
|
|
262
|
+
ax=ax_main,colorbar_flag=False,title_flag=False,
|
|
263
|
+
projection=projection,axislabels_flag=False,title=None,
|
|
264
|
+
cmap=cmap,norm=norm)
|
|
265
|
+
|
|
266
|
+
# add_china_map_2cartopy(ax_main, name='province', facecolor='none',edgecolor=None, lw=1)
|
|
267
|
+
draw_gisinfo(ax_main,slat=ylim_south,nlat=ylim_north,wlon=xlim_west,elon=xlim_east)
|
|
268
|
+
# draw_topo()
|
|
269
|
+
# point_lat = 30.72
|
|
270
|
+
# point_lon = 108.57
|
|
271
|
+
# ax_main.plot(point_lon,point_lat,marker='o',color='k',markersize=6,transform=ccrs.PlateCarree())
|
|
272
|
+
infostr = '中央气象台-天气预报技术研发室 制作(试验产品)'
|
|
273
|
+
# infostr = '贵州省气象台制作(试验产品)'
|
|
274
|
+
fig.text(0.05,0.03, infostr, va="center", ha="left", font=font_mid )
|
|
275
|
+
|
|
276
|
+
ax_main.set_ylim([ylim_south, ylim_north])
|
|
277
|
+
ax_main.set_xlim([xlim_west, xlim_east])
|
|
278
|
+
ax_main.set_xticks([])
|
|
279
|
+
ax_main.set_yticks([])
|
|
280
|
+
ax_main.set_xlabel('')
|
|
281
|
+
ax_main.set_ylabel('')
|
|
282
|
+
plt.title('')
|
|
283
|
+
|
|
284
|
+
ax_top = fig.add_axes(ax_pos_top)
|
|
285
|
+
# ax_top.axis('equal')
|
|
286
|
+
x_1d = grid.x['data'] / 1000
|
|
287
|
+
y_1d = grid.y['data'] / 1000
|
|
288
|
+
z_1d = grid.z['data'] / 1000
|
|
289
|
+
# data = self.grid.fields[field]['data'][:, y_index, :]
|
|
290
|
+
# data = np.ma.masked_outside(data, vmin, vmax)
|
|
291
|
+
|
|
292
|
+
ref = grid.fields[field]['data']
|
|
293
|
+
data1 = np.max(ref,1)
|
|
294
|
+
xd, zd = np.meshgrid(x_1d, z_1d)
|
|
295
|
+
pm_top = ax_top.pcolormesh(
|
|
296
|
+
xd, zd, data1, vmin=vmin, vmax=vmax,cmap=cmap )
|
|
297
|
+
ax_top.set_ylim([0, 20])
|
|
298
|
+
plt.yticks([0,5,10,15,20])
|
|
299
|
+
plt.xticks([])
|
|
300
|
+
plt.title('经度-高度图(公里)(沿经向取最大值)',fontproperties=font_mid)
|
|
301
|
+
plt.grid(color='k',axis='y')
|
|
302
|
+
|
|
303
|
+
ax_right = fig.add_axes(ax_pos_right)
|
|
304
|
+
data2 = np.max(ref,2)
|
|
305
|
+
zd, xd = np.meshgrid(z_1d, x_1d)
|
|
306
|
+
pm_right = ax_right.pcolormesh(
|
|
307
|
+
zd, xd, data2.T, vmin=vmin, vmax=vmax,cmap=cmap )
|
|
308
|
+
ax_right.set_xlim([0, 20])
|
|
309
|
+
plt.xticks([0,5,10,15,20])
|
|
310
|
+
plt.yticks([])
|
|
311
|
+
plt.title('纬度-高度图(公里)\n(沿纬向取最大值)',fontproperties=font_mid)
|
|
312
|
+
plt.grid(color='k',axis='x')
|
|
313
|
+
|
|
314
|
+
# add colorbar
|
|
315
|
+
ax_cbar = fig.add_axes(ax_pos_cbar)
|
|
316
|
+
cb=plt.colorbar(pm_right,cax=ax_cbar,orientation='vertical')#方向
|
|
317
|
+
plt.title('dBZ')
|
|
318
|
+
plt.savefig(outpath + os.sep + filename.replace('.nc','.png'),dpi=600)
|
|
319
|
+
plt.close()
|
|
320
|
+
# plt.show()
|
|
321
|
+
# create axis
|
|
322
|
+
|
|
323
|
+
pass
|
|
324
|
+
|
|
325
|
+
if __name__ == "__main__":
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
path = '/Users/wenjianzhu/Downloads/20230727重庆/FMT/mosaic_pyart'
|
|
329
|
+
outpath = '/Users/wenjianzhu/Downloads/20230727重庆/FMT/mosaic_3d_pic'
|
|
330
|
+
|
|
331
|
+
colorfile='/Users/wenjianzhu/Library/CloudStorage/OneDrive-个人/PythonCode/MyWork/nmc_met_radar/resources/gr2_colors/default_BR_PUP2.pal'
|
|
332
|
+
for file in os.listdir(path):
|
|
333
|
+
if not file.endswith('.nc'):
|
|
334
|
+
continue
|
|
335
|
+
draw_composite_operational(path + os.sep + file,outpath,colorfile=colorfile)
|
|
336
|
+
pass
|
|
337
|
+
|
|
338
|
+
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
#!/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
Extrapolation nowcast
|
|
4
|
+
=====================
|
|
5
|
+
|
|
6
|
+
This tutorial shows how to compute and plot an extrapolation nowcast using
|
|
7
|
+
Finnish radar data.
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
import matplotlib.pyplot as plt
|
|
13
|
+
import numpy as np
|
|
14
|
+
from pprint import pprint
|
|
15
|
+
from pysteps import io, motion, nowcasts, rcparams, verification
|
|
16
|
+
from pysteps.utils import conversion, transformation
|
|
17
|
+
from pysteps.visualization import plot_precip_field, quiver
|
|
18
|
+
import os
|
|
19
|
+
import xarray as xr
|
|
20
|
+
from draw_mosaic_new import draw_mosaic
|
|
21
|
+
from datetime import datetime, timedelta
|
|
22
|
+
import matplotlib
|
|
23
|
+
matplotlib.use('MacOSX')
|
|
24
|
+
###############################################################################
|
|
25
|
+
# Read the radar input images
|
|
26
|
+
# ---------------------------
|
|
27
|
+
#
|
|
28
|
+
# First, we will import the sequence of radar composites.
|
|
29
|
+
# You need the pysteps-data archive downloaded and the pystepsrc file
|
|
30
|
+
# configured with the data_source paths pointing to data folders.
|
|
31
|
+
|
|
32
|
+
# Selected case
|
|
33
|
+
# date = datetime.strptime("201609281600", "%Y%m%d%H%M")
|
|
34
|
+
date = datetime.strptime("202304211800", "%Y%m%d%H%M")
|
|
35
|
+
data_source = rcparams.data_sources["fmi"]
|
|
36
|
+
n_leadtimes = 12
|
|
37
|
+
|
|
38
|
+
###############################################################################
|
|
39
|
+
# Load the data from the archive
|
|
40
|
+
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
41
|
+
|
|
42
|
+
root_path = data_source["root_path"]
|
|
43
|
+
path_fmt = data_source["path_fmt"]
|
|
44
|
+
fn_pattern = data_source["fn_pattern"]
|
|
45
|
+
fn_ext = data_source["fn_ext"]
|
|
46
|
+
importer_name = data_source["importer"]
|
|
47
|
+
importer_kwargs = data_source["importer_kwargs"]
|
|
48
|
+
timestep = data_source["timestep"]
|
|
49
|
+
|
|
50
|
+
# Find the input files from the archive
|
|
51
|
+
fns = io.archive.find_by_date(
|
|
52
|
+
date, root_path, path_fmt, fn_pattern, fn_ext, timestep, num_prev_files=2
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Read the radar composites
|
|
56
|
+
importer = io.get_method(importer_name, "importer")
|
|
57
|
+
Z, _, metadata = io.read_timeseries(fns, importer, **importer_kwargs)
|
|
58
|
+
|
|
59
|
+
# write Z to ds
|
|
60
|
+
# set longitude and latitude coordinates
|
|
61
|
+
slat = 33
|
|
62
|
+
nlat = 37
|
|
63
|
+
wlon = 109
|
|
64
|
+
elon = 117
|
|
65
|
+
lat = np.linspace(slat,nlat,Z.shape[1])
|
|
66
|
+
lon = np.linspace(wlon,elon,Z.shape[2])
|
|
67
|
+
|
|
68
|
+
# set time coordinates
|
|
69
|
+
curtime = metadata['timestamps'][-1]
|
|
70
|
+
curtime = np.array([curtime], dtype='datetime64[m]')
|
|
71
|
+
# data = np.expand_dims(data, axis=0)
|
|
72
|
+
|
|
73
|
+
# define coordinates
|
|
74
|
+
time_coord = ('time', curtime)
|
|
75
|
+
lon_coord = ('lon', lon, {
|
|
76
|
+
'long_name':'longitude', 'units':'degrees_east', '_CoordinateAxisType':'Lon'})
|
|
77
|
+
lat_coord = ('lat', lat, {
|
|
78
|
+
'long_name':'latitude', 'units':'degrees_north', '_CoordinateAxisType':'Lat'})
|
|
79
|
+
|
|
80
|
+
# create xarray
|
|
81
|
+
varattrs = {'long_name': 'Composite Refelectivity',
|
|
82
|
+
'short_name': 'cref', 'units': 'dBZ',
|
|
83
|
+
'maxv':80,
|
|
84
|
+
'minv':0}
|
|
85
|
+
data = xr.Dataset({'cref':(['lat', 'lon'], np.flipud(Z[-1]), varattrs)},
|
|
86
|
+
coords={ 'lat':lat_coord, 'lon':lon_coord})
|
|
87
|
+
|
|
88
|
+
outpath = 'pic'
|
|
89
|
+
|
|
90
|
+
tstr = metadata['timestamps'][-1].strftime('%Y%m%d%H%M')
|
|
91
|
+
outname = '%s_obs.png'%tstr
|
|
92
|
+
dpi = 600
|
|
93
|
+
thred=10
|
|
94
|
+
# draw_mosaic(data.cref,data.lat.data,data.lon.data,slat,nlat,wlon,elon,outpath,outname,tstr,subtitle='实况',titlecolor='k',dpi=dpi,thred=thred)
|
|
95
|
+
# print(outpath + os.sep + outname + ' done!')
|
|
96
|
+
# Convert to rain rate
|
|
97
|
+
# R, metadata = conversion.to_rainrate(Z, metadata)
|
|
98
|
+
|
|
99
|
+
# # Plot the rainfall field
|
|
100
|
+
# fig1 = plt.figure(figsize=(6, 6))
|
|
101
|
+
# plot_precip_field(Z[-1, :, :], geodata=metadata)
|
|
102
|
+
# # plt.show()
|
|
103
|
+
|
|
104
|
+
# Store the last frame for plotting it later later
|
|
105
|
+
# R_ = R[-1, :, :].copy()
|
|
106
|
+
|
|
107
|
+
# Log-transform the data to unit of dBR, set the threshold to 0.1 mm/h,
|
|
108
|
+
# set the fill value to -15 dBR
|
|
109
|
+
# R, metadata = transformation.dB_transform(R, metadata, threshold=0.1, zerovalue=-15.0)
|
|
110
|
+
|
|
111
|
+
# Nicely print the metadata
|
|
112
|
+
# pprint(metadata)
|
|
113
|
+
|
|
114
|
+
###############################################################################
|
|
115
|
+
# Compute the nowcast
|
|
116
|
+
# -------------------
|
|
117
|
+
#
|
|
118
|
+
# The extrapolation nowcast is based on the estimation of the motion field,
|
|
119
|
+
# which is here performed using a local tracking approach (Lucas-Kanade).
|
|
120
|
+
# The most recent radar rainfall field is then simply advected along this motion
|
|
121
|
+
# field in oder to produce an extrapolation forecast.
|
|
122
|
+
|
|
123
|
+
# Estimate the motion field with Lucas-Kanade
|
|
124
|
+
# st = time.time()
|
|
125
|
+
oflow_method = motion.get_method("LK")
|
|
126
|
+
V = oflow_method(Z[-3:, :, :])
|
|
127
|
+
|
|
128
|
+
# Extrapolate the last radar observation
|
|
129
|
+
extrapolate = nowcasts.get_method("extrapolation")
|
|
130
|
+
# R[~np.isfinite(R)] = metadata["zerovalue"]
|
|
131
|
+
Z_f = extrapolate(Z[-1, :, :], V, n_leadtimes)
|
|
132
|
+
for nn in range(len(Z_f)):
|
|
133
|
+
fsttime = metadata['timestamps'][-1] + timedelta(minutes=10*(nn+1))
|
|
134
|
+
tstr = fsttime.strftime('%Y%m%d%H%M')
|
|
135
|
+
# set time coordinates
|
|
136
|
+
fsttime = np.array([fsttime], dtype='datetime64[m]')
|
|
137
|
+
# data = np.expand_dims(data, axis=0)
|
|
138
|
+
|
|
139
|
+
# define coordinates
|
|
140
|
+
time_coord = ('time', fsttime)
|
|
141
|
+
lon_coord = ('lon', lon, {
|
|
142
|
+
'long_name':'longitude', 'units':'degrees_east', '_CoordinateAxisType':'Lon'})
|
|
143
|
+
lat_coord = ('lat', lat, {
|
|
144
|
+
'long_name':'latitude', 'units':'degrees_north', '_CoordinateAxisType':'Lat'})
|
|
145
|
+
|
|
146
|
+
# create xarray
|
|
147
|
+
varattrs = {'long_name': 'Composite Refelectivity',
|
|
148
|
+
'short_name': 'cref', 'units': 'dBZ',
|
|
149
|
+
'maxv':80,
|
|
150
|
+
'minv':0}
|
|
151
|
+
data = xr.Dataset({'cref':(['lat', 'lon'], np.flipud(Z_f[nn]), varattrs)},
|
|
152
|
+
coords={ 'lat':lat_coord, 'lon':lon_coord})
|
|
153
|
+
|
|
154
|
+
outpath = 'pic'
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
outname = '%s_fst.png'%tstr
|
|
158
|
+
dpi = 600
|
|
159
|
+
thred=10
|
|
160
|
+
draw_mosaic(data.cref,data.lat.data,data.lon.data,slat,nlat,wlon,elon,outpath,outname,tstr,subtitle='预报',titlecolor='r',dpi=dpi,thred=thred,add_title=1,prefix_title='雷达组合反射率拼图')
|
|
161
|
+
# print(outpath + os.sep + outname + ' done!')
|
|
162
|
+
|
|
163
|
+
pass
|
|
164
|
+
# Back-transform to rain rate
|
|
165
|
+
# R_f = transformation.dB_transform(R_f, threshold=-10.0, inverse=True)[0]
|
|
166
|
+
|
|
167
|
+
# et = time.time()
|
|
168
|
+
# print("Execution time(s): ", et - st)
|
|
169
|
+
# Plot the motion field
|
|
170
|
+
# fig2 = plt.figure(figsize=(6, 6))
|
|
171
|
+
# plot_precip_field(Z_f[-1,:,:], geodata=metadata)
|
|
172
|
+
# quiver(V, geodata=metadata, step=50)
|
|
173
|
+
# plt.show()
|
|
174
|
+
|
|
175
|
+
###############################################################################
|
|
176
|
+
# Verify with FSS
|
|
177
|
+
# ---------------
|
|
178
|
+
#
|
|
179
|
+
# The fractions skill score (FSS) provides an intuitive assessment of the
|
|
180
|
+
# dependency of skill on spatial scale and intensity, which makes it an ideal
|
|
181
|
+
# skill score for high-resolution precipitation forecasts.
|
|
182
|
+
|
|
183
|
+
# Find observations in the data archive
|
|
184
|
+
fns = io.archive.find_by_date(
|
|
185
|
+
date,
|
|
186
|
+
root_path,
|
|
187
|
+
path_fmt,
|
|
188
|
+
fn_pattern,
|
|
189
|
+
fn_ext,
|
|
190
|
+
timestep,
|
|
191
|
+
num_prev_files=0,
|
|
192
|
+
num_next_files=n_leadtimes,
|
|
193
|
+
)
|
|
194
|
+
# Read the radar composites
|
|
195
|
+
Z_o, _, metadata_o = io.read_timeseries(fns, importer, **importer_kwargs)
|
|
196
|
+
# R_o, metadata_o = conversion.to_rainrate(R_o, metadata_o, 223.0, 1.53)
|
|
197
|
+
|
|
198
|
+
# Compute fractions skill score (FSS) for all lead times, a set of scales and 1 mm/h
|
|
199
|
+
fss = verification.get_method("FSS")
|
|
200
|
+
scales = [2, 4, 8, 16, 32, 64, 128]
|
|
201
|
+
thr = 5.0
|
|
202
|
+
score = []
|
|
203
|
+
for i in range(n_leadtimes):
|
|
204
|
+
score_ = []
|
|
205
|
+
for scale in scales:
|
|
206
|
+
score_.append(fss(Z_f[i, :, :], Z_o[i + 1, :, :], thr, scale))
|
|
207
|
+
score.append(score_)
|
|
208
|
+
|
|
209
|
+
# plt.figure()
|
|
210
|
+
# fig3 = plt.figure(figsize=(6, 6))
|
|
211
|
+
# x = np.arange(1, n_leadtimes + 1) * timestep
|
|
212
|
+
# plt.plot(x, score)
|
|
213
|
+
# plt.legend(scales, title="Scale [km]")
|
|
214
|
+
# plt.xlabel("Lead time [min]")
|
|
215
|
+
# plt.ylabel("FSS ( > 5 dBZ ) ")
|
|
216
|
+
# plt.title("Fractions skill score")
|
|
217
|
+
# plt.show()
|
|
218
|
+
|
|
219
|
+
# sphinx_gallery_thumbnail_number = 3
|