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.
Files changed (41) hide show
  1. metradar/__init__.py +7 -0
  2. metradar/cnrad_level2.py +1326 -0
  3. metradar/comm_func.py +135 -0
  4. metradar/construct_aws_refvpr_mainprog.py +515 -0
  5. metradar/construct_aws_refvpr_mainprog_cams.py +310 -0
  6. metradar/construct_aws_refvpr_mainprog_datan3d.py +386 -0
  7. metradar/construct_aws_refvpr_mainprog_swan.py +306 -0
  8. metradar/decode_fmt_pyart.py +200 -0
  9. metradar/decode_pup_rose.py +1993 -0
  10. metradar/draw_mosaic_new.py +421 -0
  11. metradar/draw_radar_aws_jilin_new.py +206 -0
  12. metradar/draw_radar_comp_func.py +1379 -0
  13. metradar/exceptions.py +50 -0
  14. metradar/geo_transforms_pyart.py +627 -0
  15. metradar/get_cross_section_from_pyart.py +354 -0
  16. metradar/get_tlogp_from_sharppy.py +93 -0
  17. metradar/grid.py +281 -0
  18. metradar/grid_data.py +64 -0
  19. metradar/main_pydda.py +653 -0
  20. metradar/make_gif.py +24 -0
  21. metradar/make_mosaic_mp_archive.py +538 -0
  22. metradar/mosaic_merge.py +64 -0
  23. metradar/mosaic_quickdraw.py +338 -0
  24. metradar/nowcast_by_pysteps.py +219 -0
  25. metradar/oa_couhua.py +166 -0
  26. metradar/oa_dig_func.py +955 -0
  27. metradar/parse_pal.py +148 -0
  28. metradar/pgmb_io.py +169 -0
  29. metradar/prepare_for_radar_draw.py +197 -0
  30. metradar/read_new_mosaic.py +33 -0
  31. metradar/read_new_mosaic_func.py +231 -0
  32. metradar/retrieve_cmadaas.py +3126 -0
  33. metradar/retrieve_micaps_server.py +2061 -0
  34. metradar/rose_structer.py +807 -0
  35. metradar/trans_nc_pgmb.py +62 -0
  36. metradar/trans_new_mosaic_nc.py +309 -0
  37. metradar/trans_polor2grid_func.py +203 -0
  38. metradar-0.1.0.dist-info/METADATA +12 -0
  39. metradar-0.1.0.dist-info/RECORD +41 -0
  40. metradar-0.1.0.dist-info/WHEEL +5 -0
  41. metradar-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1379 @@
1
+ '''
2
+ 画雷达综合图主程序
3
+
4
+ '''
5
+
6
+ import pyart
7
+ import os
8
+ import numpy as np
9
+ import numpy.ma as MA
10
+
11
+ import matplotlib.pyplot as plt
12
+ import cartopy.crs as ccrs
13
+
14
+ from netCDF4 import num2date
15
+ import xarray
16
+ from cartopy.io.shapereader import Reader
17
+ from matplotlib.font_manager import FontProperties
18
+ import pandas as pd
19
+ from metpy.calc import wind_components
20
+ from metpy.units import units
21
+ from parse_pal import parse_pro
22
+ from matplotlib.colorbar import ColorbarBase
23
+ import matplotlib.patheffects as path_effects
24
+ from matplotlib import patheffects
25
+ import matplotlib.transforms as transforms
26
+ from matplotlib.transforms import offset_copy
27
+ from oa_dig_func import Object_Analyst
28
+ import warnings
29
+ warnings.filterwarnings('ignore')
30
+ import matplotlib as mpl
31
+ from get_cross_section_from_pyart import get_cross_radar
32
+ # from adjustText import adjust_text
33
+ import matplotlib
34
+ matplotlib.use('Agg')
35
+ # matplotlib.use('MacOSX')
36
+ from matplotlib import ticker
37
+ import xarray as xr
38
+
39
+ # 初始化参数字典,用于存储绘图所需的所有参数
40
+ def ini_params():
41
+ param={'radarfile_path':None, # 雷达文件路径
42
+ 'radarfile_name':None, # 雷达文件名
43
+ 'mosaicfile_path':None,# 反射率拼图文件路径
44
+ 'mosaicfile_name':None, # 反射率拼图文件名
45
+ 'pic_path':None, # 图片保存路径
46
+ 'timestr':None, # 图片时间
47
+ 'aws_min_file_path':None, # aws分钟数据文件路径
48
+ 'aws_min_file_name':None, # aws分钟数据文件名
49
+ 'aws_hour_file_path':None, # aws小时数据文件路径
50
+ 'aws_hour_file_name':None,# aws小时数据文件名
51
+
52
+ 'aws_min_delta_t_file_path':None, # aws小时变温数据文件路径
53
+ 'aws_min_delta_t_file_name':None,# aws小时变温数据文件名
54
+ 'aws_min_delta_p_file_path':None, # aws小时变压数据文件路径
55
+ 'aws_min_delta_p_file_name':None,# aws小时变压数据文件名
56
+
57
+ 'gis_name':None, # 站点名称
58
+ 'gis_lats':None, # 站点纬度
59
+ 'gis_lons':None, # 站点经度
60
+ 'slat':None, # 绘图区域南纬
61
+ 'nlat':None, # 绘图区域北纬
62
+ 'wlon':None, # 绘图区域西经
63
+ 'elon':None, # 绘图区域东经
64
+ 'ref_colorfile':None, # 回波强度色标文件
65
+ 'vel_colorfile':None, # 径向速度色标文件
66
+ 'cc_colorfile':None, # 相关系数色标文件
67
+ 'zdr_colorfile':None, # 差分反射率色标文件
68
+ 'kdp_colorfile':None, # 差分相移率色标文件
69
+ 'fontfile':None, # 字体文件
70
+ 'dpi':300, # 图片分辨率
71
+ 'pic_format':'png', # 图片格式
72
+ 'figsize_width':4, # 图片宽度
73
+ 'figsize_height':4, # 图片高度
74
+ 'fontsize_gis':4, # GIS字体大小
75
+ 'fontsize_colorbar':3, # 色标字体大小
76
+ 'fontsize_title':4,# 标题字体大小
77
+ 'fontsize_tick':6, # 坐标轴刻度字体大小
78
+ 'bdraw_title_ppi':True, # 是否给PPI图绘制标题
79
+ 'bdraw_title_crs':True, # 是否给垂直剖面图绘制标题
80
+ 'mapcolor':[170/255,170/255,170/255], # 行政边界颜色
81
+ 'linewidth_map': 0.5,# 行政边界线宽
82
+ 'contour_color':[0/255,0/255,0/255], # 等值线颜色
83
+ 'linewidth_cntr': 0.8,# 等值线线宽
84
+ 'breplace':True, #如果图片文件已存在,是否重新绘制
85
+ 'bdraw_crs':False, # 是否绘制垂直剖面图
86
+ 'thred_pre1h': 30, # 1小时降水阈值
87
+ 'thred_ref':0, # 回波强度阈值
88
+ 'radarname': 'XX',# 雷达站名
89
+
90
+
91
+ }
92
+ return param
93
+
94
+
95
+ # FuncFormatter can be used as a decorator
96
+ @ticker.FuncFormatter
97
+ def major_formatter_lon(x, pos):
98
+ return f'{x:.1f}°E'
99
+
100
+ @ticker.FuncFormatter
101
+ def major_formatter_lat(x, pos):
102
+ return f'{x:.1f}°N'
103
+
104
+ class DRAW_RADAR_OTHER:
105
+
106
+ def __init__(self,params):
107
+ pass
108
+ self.radarfile_path=params['radarfile_path']
109
+ self.radarfile_name=params['radarfile_name']
110
+ self.mosaicfile_path=params['mosaicfile_path']
111
+ self.mosaicfile_name=params['mosaicfile_name']
112
+ self.aws_min_file_path=params['aws_min_file_path']
113
+ self.aws_min_file_name=params['aws_min_file_name']
114
+
115
+ self.aws_min_delta_t_file_path=params['aws_min_delta_t_file_path']
116
+ self.aws_min_delta_t_file_name=params['aws_min_delta_t_file_name']
117
+ self.aws_min_delta_p_file_path=params['aws_min_delta_p_file_path']
118
+ self.aws_min_delta_p_file_name=params['aws_min_delta_p_file_name']
119
+
120
+ self.aws_hour_file_path=params['aws_hour_file_path']
121
+ self.aws_hour_file_name=params['aws_hour_file_name']
122
+ self.gis_name=params['gis_name']
123
+ self.gis_lats=params['gis_lats']
124
+ self.gis_lons=params['gis_lons']
125
+ self.slat=params['slat']
126
+ self.nlat=params['nlat']
127
+ self.wlon=params['wlon']
128
+ self.elon=params['elon']
129
+ self.ref_colorfile=params['ref_colorfile']
130
+ self.vel_colorfile=params['vel_colorfile']
131
+ self.cc_colorfile=params['cc_colorfile']
132
+ self.zdr_colorfile=params['zdr_colorfile']
133
+ self.fontfile=params['fontfile']
134
+ self.picpath=params['pic_path']
135
+ self.timestr=params['timestr']
136
+ self.breplace=params['breplace']
137
+ self.mapcolor=params['mapcolor']
138
+ self.linewidth_map=params['linewidth_map']
139
+ self.contour_color=params['contour_color']
140
+ self.linewidth_cntr=params['linewidth_cntr']
141
+ self.dpi = params['dpi']
142
+ self.paintsize_x = params['figsize_width']
143
+ self.paintsize_y = params['figsize_height']
144
+
145
+ self.gatefilter_ref = None
146
+ self.pic_format = params['pic_format']
147
+ self.fontsize_gis=params['fontsize_gis']
148
+ self.fontsize_colorbar=params['fontsize_colorbar']
149
+ self.fontsize_title=params['fontsize_title']
150
+ self.bdraw_title_ppi=params['bdraw_title_ppi']
151
+ self.bdraw_title_crs=params['bdraw_title_crs']
152
+ self.crs_paintsize_x = params['figsize_width']
153
+ self.bdraw_crs=params['bdraw_crs']
154
+ self.fontsize_tick=params['fontsize_tick']
155
+ self.thred_pre1h=params['thred_pre1h']
156
+ self.thred_ref =params['thred_ref']
157
+ self.radarname = params['radarname']
158
+ self.linewidth_cntr = params['linewidth_cntr']
159
+ if self.bdraw_crs == True:
160
+ self.crs_start_azi=params['crs_start_azi']
161
+ self.crs_end_azi=params['crs_end_azi']
162
+ self.crs_start_range=params['crs_start_range']
163
+ self.crs_end_range=params['crs_end_range']
164
+ self.top_height = params['top_height']
165
+
166
+ else:
167
+ self.crs_start_azi=None
168
+ self.crs_end_azi=None
169
+ self.crs_start_range=None
170
+ self.crs_end_range=None
171
+ self.top_height = None
172
+
173
+ try:
174
+ if not os.path.exists(self.picpath): os.makedirs(self.picpath)
175
+ except:
176
+ pass
177
+
178
+ self.ratio = (self.nlat - self.slat)/(self.elon-self.wlon)
179
+
180
+ # self.paintsize_y=(self.paintsize_x*self.ratio)
181
+
182
+
183
+ # 设置坐标轴字体大小
184
+ # matplotlib.rc('xtick', labelsize=self.fontsize_tick)
185
+ # matplotlib.rc('ytick', labelsize=self.fontsize_tick)
186
+ mpl.rcParams['font.size'] = self.fontsize_tick
187
+ mpl.rcParams['font.weight'] = 'bold'
188
+ mpl.rcParams['font.family'] = 'Times New Roman'
189
+ mpl.rcParams['xtick.direction'] = 'in' # 'out' 'inout'
190
+ mpl.rcParams['ytick.direction'] = 'in' # 'out' 'inout'
191
+
192
+ self.cref=None
193
+ self.voltime = None
194
+
195
+ self.disratio = self.paintsize_x / 2
196
+ # self.disratio=1
197
+
198
+ self.font_gis=FontProperties(fname=self.fontfile, size=self.fontsize_gis)
199
+ self.font_colorbar=FontProperties(fname=self.fontfile, size=self.fontsize_colorbar)
200
+ self.font_indicate=FontProperties(fname=self.fontfile, size=self.fontsize_colorbar*2)
201
+ self.font_title=FontProperties(fname=self.fontfile, size=self.fontsize_title)
202
+ self.stroke_line_width=1 * self.disratio
203
+ self.cref=None
204
+ self.voltime = None
205
+ self.crs_data=None
206
+ self.crs_fig=None
207
+
208
+ # self.axes_pos = [0.01, 0.06, 0.98, 0.88]
209
+ self.axes_pos = [0.05, 0.07, 0.9, 0.9]
210
+ self.cbaxes_pos = [0.05, 0.01, 0.9, 0.05]
211
+ # self.cbaxes_pos = [0.8,0.15,0.02,0.6]
212
+
213
+ self.crs_axes_pos = [0.15, 0.15, 0.70, 0.8]
214
+ self.crs_cbaxes_pos = [0.86, 0.15, 0.03, 0.8]
215
+ self.radar = None
216
+
217
+ def read_vol_data(self,):
218
+ # filepath = 'data/'
219
+ # filename = 'ZZHN.20210720.180000.ar2v'
220
+ if self.radarfile_name is None:
221
+ print('no valid radfile!')
222
+ return False
223
+ if not os.path.exists(self.radarfile_path + os.sep + self.radarfile_name):
224
+ print(self.radarfile_path + os.sep + self.radarfile_name + ' not exists!')
225
+ return False
226
+ self.radar = pyart.io.read_nexrad_archive(self.radarfile_path + os.sep + self.radarfile_name)
227
+ # self.radar.fields.keys()
228
+ self.display = pyart.graph.RadarMapDisplay(self.radar)
229
+ self.gatefilter_ref = pyart.correct.GateFilter(self.radar)
230
+ self.gatefilter_ref.exclude_below('reflectivity', self.thred_ref, exclude_masked=True, op='or', inclusive=False)
231
+
232
+
233
+ self.g_rad_lon = self.radar.longitude['data'][0]
234
+ self.g_rad_lat = self.radar.latitude['data'][0]
235
+
236
+ times_t = self.radar.time['data'][0]
237
+ units_t = self.radar.time['units']
238
+ calendar = self.radar.time['calendar']
239
+ voltime= num2date(times_t, units_t, calendar, only_use_cftime_datetimes=False,
240
+ only_use_python_datetimes=True)
241
+ datetime_format='%Y%m%d-%H:%M'
242
+ self.voltime = voltime.strftime(datetime_format)
243
+ return True
244
+
245
+ def get_crs_from_radar(self,):
246
+ pass
247
+ param_crs=dict()
248
+ param_crs['crs_start_azi'] = self.crs_start_azi
249
+ param_crs['crs_start_range'] = self.crs_start_range
250
+ param_crs['crs_end_azi'] = self.crs_end_azi
251
+ param_crs['crs_end_range'] = self.crs_end_range
252
+ param_crs['top_height'] = self.top_height
253
+ # st = time.time()
254
+ if self.radar is None:
255
+ return False
256
+ # self.gatefilter_ref = pyart.correct.GateFilter(self.radar)
257
+ # self.gatefilter_ref.exclude_below('reflectivity', thred, exclude_masked=True, op='and', inclusive=True)
258
+ self.crs_data = get_cross_radar(self.radar,param_crs)
259
+ pass
260
+ # et = time.time()
261
+ # print('get cross data costs %.1f seconds!'%(et-st))
262
+
263
+ def draw_crs(self,subdir='垂直剖面',varname=None,brefresh=False,thred=None,):
264
+ # check
265
+
266
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.jpg') and not brefresh:
267
+ return False
268
+ if self.crs_data is None:
269
+ print('warning: crs_data not pre loaded!')
270
+ return False
271
+
272
+ if varname is None:
273
+ print('warning: varname is None!')
274
+ return False
275
+
276
+ if not thred is None:
277
+ flag = self.crs_data[varname] < thred
278
+ self.crs_data[varname] = MA.masked_array(self.crs_data[varname], mask=flag)
279
+
280
+ colorfile = self.ref_colorfile
281
+ if varname.find('ref') >=0:
282
+ colorfile = self.ref_colorfile
283
+ elif varname.find('vel') >=0:
284
+ colorfile = self.vel_colorfile
285
+ else:
286
+ print('warning: varname = %s not config the colorfile in the draw_crs function!'%varname)
287
+ return False
288
+
289
+ colordata = parse_pro(colorfile)
290
+
291
+ # self.crs_ratio = self.crs_data['vertical_km'] / self.crs_data['horizontal_km'] * 0.8
292
+ self.crs_ratio = 0.6
293
+ self.crs_paintsize_y = self.crs_paintsize_x * self.crs_ratio
294
+ self.crs_fig = plt.figure(figsize=(self.crs_paintsize_x,self.crs_paintsize_y))
295
+ map_panel_axes = self.crs_axes_pos
296
+ self.crs_ax = self.crs_fig.add_axes(map_panel_axes)
297
+ plt.pcolormesh(self.crs_data[varname],cmap=colordata['cmap'],norm=colordata['norm'])
298
+ xticks = self.crs_ax.get_xticks()
299
+ if xticks[-1] < self.crs_data[varname].shape[1]:
300
+ xticks.append(self.crs_data[varname].shape[1])
301
+ else:
302
+ xticks[-1] = self.crs_data[varname].shape[1]
303
+
304
+ xticklabels = []
305
+ for ix in range(len(xticks)):
306
+ xticklabels.append('%.1f'%(xticks[ix]*self.crs_data['xreso']))
307
+ xticklabels[0]='A'
308
+ xticklabels[-1]='B'
309
+
310
+ self.crs_ax.set_xticks(xticks)
311
+ self.crs_ax.set_xticklabels(xticklabels)
312
+
313
+ yticks = self.crs_ax.get_yticks()
314
+ if yticks[-1] < self.crs_data[varname].shape[0]:
315
+ yticks.append(self.crs_data[varname].shape[0])
316
+ yticklabels = []
317
+ for iy in range(len(yticks)):
318
+ yticklabels.append('%.1f'%(yticks[iy]*self.crs_data['yreso']))
319
+
320
+ self.crs_ax.set_yticklabels(yticklabels)
321
+ self.crs_ax.set_xlabel('水平距离(KM)',font=self.font_colorbar)
322
+ self.crs_ax.set_ylabel('垂直高度(KM)',font=self.font_colorbar)
323
+ plt.grid()
324
+ self.draw_title_crs(varname=varname)
325
+ self.draw_crs_colorbar(colorfile=colorfile)
326
+ self.crs_finish_save(subdir=subdir,add_str=varname,)
327
+
328
+ def draw_title_crs(self,varname='reflectivity'):
329
+ if not self.bdraw_title_crs:
330
+ return None
331
+ # titlestr = 'Cross section of ' + varname + ' '
332
+ [x,y,z]=pyart.core.antenna_to_cartesian(self.crs_start_range, self.crs_start_azi, elevations=0)
333
+ [start_lon,start_lat]=pyart.core.cartesian_to_geographic_aeqd(x,y,self.g_rad_lon,self.g_rad_lat)
334
+ [x,y,z]=pyart.core.antenna_to_cartesian(self.crs_end_range, self.crs_end_azi, elevations=0)
335
+ [end_lon,end_lat]=pyart.core.cartesian_to_geographic_aeqd(x,y,self.g_rad_lon,self.g_rad_lat)
336
+ self.crs_startlat = start_lat
337
+ self.crs_startlon = start_lon
338
+ self.crs_endlat = end_lat
339
+ self.crs_endlon = end_lon
340
+ titlestr = 'A(%.2f,%.2f)->B(%.2f,%.2f) '%(self.crs_startlon,self.crs_startlat,self.crs_endlon,self.crs_endlat)
341
+ tstr=''
342
+ if self.voltime is None:
343
+ tstr = self.timestr
344
+ else:
345
+ tstr = self.voltime
346
+ # titlestr += tstr + ' UTC'
347
+ plt.title('%s'%(titlestr),fontproperties=self.font_title,loc='right',verticalalignment='top')
348
+
349
+ def draw_crs_colorbar(self,fig=None,colorfile=None,tickstep=5,orientation = 'vertical',cb_ratio=0.618):
350
+ # 画色标
351
+ ax_pos = self.crs_ax.get_position().bounds
352
+ cbar_axes = [ax_pos[0]+ ax_pos[2]+0.005,(ax_pos[1]+ax_pos[1]+ax_pos[3])/2-ax_pos[3]*cb_ratio/2,0.02,ax_pos[3]*cb_ratio]
353
+ # cbar_axes = self.crs_cbaxes_pos
354
+ cb_ax = self.crs_fig.add_axes(cbar_axes)
355
+ colordata = parse_pro(colorfile)
356
+
357
+ cbar = ColorbarBase(cb_ax, orientation=orientation, norm=colordata['norm'], cmap=colordata['cmap'],extend='both')
358
+ cbar.set_ticks([])
359
+ # cb_ax.axis('tight')
360
+
361
+ trans = transforms.blended_transform_factory(cb_ax.transData, cb_ax.transAxes)
362
+ tick_poss=np.arange(colordata['norm'].vmin, colordata['norm'].vmax, tickstep)
363
+ xrange = colordata['norm'].vmax - colordata['norm'].vmin
364
+
365
+ for tick_pos in tick_poss:
366
+ cb_ax.hlines(tick_pos, colordata['norm'].vmin, colordata['norm'].vmin + 0.3*xrange, color="black",linewidth=0.5)
367
+ cb_ax.hlines(tick_pos, colordata['norm'].vmin + 0.7*xrange, colordata['norm'].vmax, color="black",linewidth=0.5)
368
+
369
+ # cb_ax.text(1.02,tick_pos, str(int(tick_pos)),color=[1,1,1],
370
+ # path_effects=[path_effects.Stroke(linewidth=self.stroke_line_width, foreground='black'),
371
+ # path_effects.Normal()],
372
+ # va="center", ha="left",font=self.font_colorbar)
373
+
374
+ cb_ax.text(1.04,tick_pos, str(int(tick_pos)),va="center", ha="left",fontsize=5) # font=self.font_colorbar
375
+
376
+ cb_ax.text(1.8, 1.035, colordata['units'], transform=cb_ax.transAxes,va="center", ha="center", fontsize=5 ) # font=self.font_colorbar
377
+ # color=[1,1,1],path_effects=[path_effects.Stroke(linewidth=self.stroke_line_width, foreground='black'),path_effects.Normal()],
378
+
379
+
380
+ def add_crs_line(self,ax=None):
381
+ pass
382
+ if not self.bdraw_crs:
383
+ # print('warning: bdraw_crs is False!')
384
+ return False
385
+
386
+ if ax is None:
387
+ print('warning: ax is None in function add_crs_line!')
388
+ return False
389
+
390
+ [x,y,z]=pyart.core.antenna_to_cartesian(self.crs_start_range, self.crs_start_azi, elevations=0)
391
+ [start_lon,start_lat]=pyart.core.cartesian_to_geographic_aeqd(x,y,self.g_rad_lon,self.g_rad_lat)
392
+ [x,y,z]=pyart.core.antenna_to_cartesian(self.crs_end_range, self.crs_end_azi, elevations=0)
393
+ [end_lon,end_lat]=pyart.core.cartesian_to_geographic_aeqd(x,y,self.g_rad_lon,self.g_rad_lat)
394
+ self.crs_startlat = start_lat
395
+ self.crs_startlon = start_lon
396
+ self.crs_endlat = end_lat
397
+ self.crs_endlon = end_lon
398
+
399
+ simble_color=[0,0,0]
400
+ ax.plot([start_lon,end_lon],[start_lat,end_lat],color='k',linewidth=0.75)
401
+ ax.plot([start_lon,end_lon],[start_lat,end_lat],color=simble_color,linewidth=0.5)
402
+ ax.text(start_lon,start_lat,'A',color=simble_color,font=self.font_colorbar,
403
+ path_effects=[path_effects.Stroke(linewidth=0.25, foreground='black'),path_effects.Normal()])
404
+ ax.text(end_lon,end_lat,'B',color=simble_color,font=self.font_colorbar,
405
+ path_effects=[path_effects.Stroke(linewidth=0.25, foreground='black'),path_effects.Normal()])
406
+
407
+ def get_cref_from_mosaicfile(self,):
408
+
409
+ data = None
410
+ if not os.path.exists(self.mosaicfile_path + os.sep + self.mosaicfile_name):
411
+ print(self.mosaicfile_path + os.sep + self.mosaicfile_name + ' does not exists!')
412
+ return False
413
+ try:
414
+ data = xarray.open_dataset(self.mosaicfile_path + os.sep + self.mosaicfile_name)
415
+ except:
416
+ print(self.mosaicfile_path + os.sep + self.mosaicfile_name + ' read error!')
417
+ self.cref=None
418
+ return False
419
+ cref = data.cref.data
420
+ self.cref = (cref.astype(np.float32) - data.cref.offset)/data.cref.scale
421
+
422
+ self.cref = self.cref.transpose()
423
+ self.cref = MA.masked_array(self.cref, mask=self.cref==-32)
424
+ self.grid_lat,self.grid_lon=np.meshgrid(data.lat.data,data.lon.data)
425
+
426
+ return True
427
+
428
+
429
+ def get_cref_from_radar(self,grid_origin=[30,110]):
430
+ self.xlims=[-100,100]
431
+ self.ylims=[-100,100]
432
+ self.zlims=[1,15]
433
+ self.xreso=500
434
+ self.yreso=500
435
+ self.zreso=500
436
+ self.g_xlim = (self.xlims[0]*1000,self.xlims[1]*1000)
437
+ self.g_ylim = (self.ylims[0]*1000,self.ylims[1]*1000)
438
+ self.g_zlim = (self.zlims[0]*1000,self.zlims[1]*1000)
439
+ self.g_numx = int(len(range(self.xlims[0],self.xlims[1]))*1000/self.xreso+1) # x方向格点数
440
+ self.g_numy = int(len(range(self.ylims[0],self.ylims[1]))*1000/self.yreso+1) # y方向格点数
441
+ self.g_numz = int(len(range(self.zlims[0],self.zlims[1]))*1000/self.zreso+1) # z方向格点数
442
+
443
+ self.grid=pyart.map.grid_from_radars(
444
+ (self.radar,),
445
+ grid_origin=grid_origin,
446
+ weighting_function = 'BARNES2',
447
+ grid_shape=(self.g_numz, self.g_numy, self.g_numx),
448
+ grid_limits=(self.g_zlim, self.g_ylim, self.g_xlim),
449
+ fields=['reflectivity'])
450
+
451
+ xrdata = self.grid.to_xarray()
452
+
453
+ self.cref = np.nanmax(xrdata.reflectivity.data[0],axis=0)
454
+ self.cref = self.cref.transpose()
455
+ self.grid_lat,self.grid_lon=np.meshgrid(xrdata.lat.data,xrdata.lon.data)
456
+
457
+ def draw_cref(self,):
458
+ cmapdic= parse_pro(self.ref_colorfile)
459
+ plt.pcolormesh(self.grid_lon,self.grid_lat,self.cref,cmap=cmapdic['cmap'],norm=cmapdic['norm'])
460
+
461
+ def draw_divergence(self,zorder=2):
462
+ # cmapdic= parse_pro(self.ref_colorfile)
463
+ # plt.pcolormesh(self.grid_lon,self.grid_lat,self.cref,cmap=cmapdic['cmap'],norm=cmapdic['norm'])
464
+ # 叠加涡度场
465
+ # filepath_minute='temp/backup_aws_minute'
466
+ # filename_aws='surface_aws_20210720_1800.csv'
467
+ if self.aws_min_file_name is None:
468
+ print('warning: aws_min_file_name is None!')
469
+ return False
470
+ if not os.path.exists(self.aws_min_file_path + os.sep + self.aws_min_file_name):
471
+ print(self.aws_min_file_path + os.sep + self.aws_min_file_name + ' does not exists!')
472
+ return False
473
+ awsdata = pd.read_csv(self.aws_min_file_path + os.sep + self.aws_min_file_name,encoding='GBK')
474
+
475
+ aws_lats=awsdata['Lat'].values
476
+ aws_lons=awsdata['Lon'].values
477
+ aws_2minspd=awsdata['WIN_S_Avg_2mi'].values
478
+ aws_2mindir=awsdata['WIN_D_Avg_2mi'].values
479
+ # u,v=wind_components(aws_2minspd,aws_2mindir)
480
+
481
+ validflag=[]
482
+ for nn in range(len(aws_lats)):
483
+ if aws_2minspd[nn] > 999000 or aws_2mindir[nn] > 999000 or aws_2minspd[nn] < 1:
484
+ continue
485
+ else:
486
+ validflag.append(nn)
487
+ aws_2minspd = aws_2minspd[validflag]*units('m/s')
488
+ aws_2mindir = aws_2mindir[validflag]*units.degree
489
+ oa_class = Object_Analyst()
490
+ oa_class.set_reso(0.01)
491
+ vtx_div = oa_class.calc_vor_div(aws_2minspd,aws_2mindir,aws_lons,aws_lats)
492
+
493
+ levels = list(range(-80, 80, 2))
494
+
495
+ cntr = self.ax1.contour(vtx_div.lon.values,vtx_div.lat.values,vtx_div.div_10m.values,
496
+ levels=levels,colors=self.contour_color,zorder=zorder,linewidths=self.linewidth_cntr)
497
+
498
+ plt.setp(cntr.collections, path_effects=[
499
+ patheffects.withStroke(linewidth=self.linewidth_cntr, foreground="w")])
500
+ clbls = self.ax1.clabel(cntr,fmt="%2.1f",use_clabeltext=True,fontsize=self.fontsize_colorbar)
501
+
502
+ plt.setp(cntr.labelTexts, path_effects=[
503
+ patheffects.withStroke(linewidth=self.linewidth_cntr, foreground="w")])
504
+
505
+ # 画温度场客观分析等值线
506
+ def draw_temperature(self,zorder=2):
507
+ if self.aws_min_file_name is None:
508
+ print('warning: aws_min_file_name is None!')
509
+ return False
510
+ if not os.path.exists(self.aws_min_file_path + os.sep + self.aws_min_file_name):
511
+ print(self.aws_min_file_path + os.sep + self.aws_min_file_name + ' does not exists!')
512
+ return False
513
+ awsdata = pd.read_csv(self.aws_min_file_path + os.sep + self.aws_min_file_name,encoding='GBK')
514
+
515
+ aws_lats=awsdata['Lat'].values
516
+ aws_lons=awsdata['Lon'].values
517
+ aws_tem = awsdata['TEM'] # 温度
518
+ aws_dpt = awsdata['DPT'] # 露点
519
+
520
+ validflag=[]
521
+ for nn in range(len(aws_lats)):
522
+ if aws_tem[nn] > 999000 :
523
+ continue
524
+ else:
525
+ validflag.append(nn)
526
+ aws_tem = aws_tem[validflag]
527
+ aws_lons = aws_lons[validflag]
528
+ aws_lats = aws_lats[validflag]
529
+
530
+ oa_class = Object_Analyst()
531
+ oa_class.set_reso(0.01)
532
+ params={}
533
+ params['in_lon'] = aws_lons
534
+ params['in_lat'] = aws_lats
535
+ params['in_data'] = aws_tem
536
+ params['out_varname'] = 't2m'
537
+ params['out_long_name'] = 'surface temperature objective analyse'
538
+ params['out_short_name'] = 'oa_t'
539
+ params['out_units'] = 'degC'
540
+
541
+ t2m = oa_class.do_oa_base(params)
542
+
543
+ # levels = list(range(-40, 50, 0.5))
544
+ levels = np.arange(-40,50,0.5)
545
+
546
+
547
+ cntr = self.ax1.contour(t2m.lon.values,t2m.lat.values,t2m.t2m.values,
548
+ levels=levels,colors='k',zorder=zorder)
549
+
550
+ plt.setp(cntr.collections, path_effects=[
551
+ patheffects.withStroke(linewidth=2, foreground="w")])
552
+ clbls = self.ax1.clabel(cntr,fmt="%2.1f",use_clabeltext=True,fontsize=self.fontsize_colorbar)
553
+
554
+ plt.setp(cntr.labelTexts, path_effects=[
555
+ patheffects.withStroke(linewidth=2, foreground="w")])
556
+
557
+ # for txobj in cntr.labelTexts:
558
+ # pos = txobj.get_position()
559
+ # txt = txobj.get_text()
560
+ # print(pos, txt)
561
+
562
+ # 画露点温度场客观分析等值线
563
+ def draw_drewpoint(self,zorder=2):
564
+ if self.aws_min_file_name is None:
565
+ print('warning: aws_min_file_name is None!')
566
+ return False
567
+ if not os.path.exists(self.aws_min_file_path + os.sep + self.aws_min_file_name):
568
+ print(self.aws_min_file_path + os.sep + self.aws_min_file_name + ' does not exists!')
569
+ return False
570
+ awsdata = pd.read_csv(self.aws_min_file_path + os.sep + self.aws_min_file_name,encoding='GBK')
571
+
572
+ aws_lats=awsdata['Lat'].values
573
+ aws_lons=awsdata['Lon'].values
574
+ aws_tem = awsdata['TEM'] # 温度
575
+ aws_dpt = awsdata['DPT'] # 露点
576
+
577
+ validflag=[]
578
+ for nn in range(len(aws_lats)):
579
+ if aws_dpt[nn] > 999000 :
580
+ continue
581
+ else:
582
+ validflag.append(nn)
583
+ aws_dpt = aws_dpt[validflag]
584
+ aws_lons = aws_lons[validflag]
585
+ aws_lats = aws_lats[validflag]
586
+
587
+ oa_class = Object_Analyst()
588
+ oa_class.set_reso(0.01)
589
+ params={}
590
+ params['in_lon'] = aws_lons
591
+ params['in_lat'] = aws_lats
592
+ params['in_data'] = aws_dpt
593
+ params['out_varname'] = 'dpt2m'
594
+ params['out_long_name'] = 'surface drew temperature objective analyse'
595
+ params['out_short_name'] = 'oa_dpt'
596
+ params['out_units'] = 'degC'
597
+
598
+ dpt2m = oa_class.do_oa_base(params)
599
+
600
+ # levels = list(range(-40, 50, 0.5))
601
+ levels = np.arange(-40,50,0.5)
602
+
603
+ cntr = self.ax1.contour(dpt2m.lon.values,dpt2m.lat.values,dpt2m.dpt2m.values,
604
+ levels=levels,colors='k',zorder=zorder)
605
+
606
+ plt.setp(cntr.collections, path_effects=[
607
+ patheffects.withStroke(linewidth=2, foreground="w")])
608
+ clbls = self.ax1.clabel(cntr,fmt="%2.1f",use_clabeltext=True,fontsize=self.fontsize_colorbar)
609
+
610
+ plt.setp(cntr.labelTexts, path_effects=[
611
+ patheffects.withStroke(linewidth=2, foreground="w")])
612
+
613
+ def draw_vortex(self,zorder=2):
614
+ if self.aws_min_file_name is None:
615
+ print('warning: aws_min_file_name is None!')
616
+ return False
617
+ if not os.path.exists(self.aws_min_file_path + os.sep + self.aws_min_file_name):
618
+ print(self.aws_min_file_path + os.sep + self.aws_min_file_name + ' does not exists!')
619
+ return False
620
+ awsdata = pd.read_csv(self.aws_min_file_path + os.sep + self.aws_min_file_name,encoding='GBK')
621
+
622
+ aws_lats=awsdata['Lat'].values
623
+ aws_lons=awsdata['Lon'].values
624
+ aws_2minspd=awsdata['WIN_S_Avg_2mi'].values
625
+ aws_2mindir=awsdata['WIN_D_Avg_2mi'].values
626
+ # u,v=wind_components(aws_2minspd,aws_2mindir)
627
+
628
+ validflag=[]
629
+ for nn in range(len(aws_lats)):
630
+ if aws_2minspd[nn] > 999000 or aws_2mindir[nn] > 999000 or aws_2minspd[nn] < 1:
631
+ continue
632
+ else:
633
+ validflag.append(nn)
634
+ aws_2minspd = aws_2minspd[validflag]*units('m/s')
635
+ aws_2mindir = aws_2mindir[validflag]*units.degree
636
+ oa_class = Object_Analyst()
637
+ oa_class.set_reso(0.01)
638
+ vtx_div = oa_class.calc_vor_div(aws_2minspd,aws_2mindir,aws_lons,aws_lats)
639
+ kk=0
640
+ levels = list(range(-80, 80, 2))
641
+
642
+ cntr = self.ax1.contour(vtx_div.lon.values,vtx_div.lat.values,vtx_div.vtx_10m.values,
643
+ levels=levels,colors='k',zorder=zorder)
644
+
645
+ plt.setp(cntr.collections, path_effects=[
646
+ patheffects.withStroke(linewidth=2, foreground="w")])
647
+ clbls = self.ax1.clabel(cntr,fmt="%2.1f",use_clabeltext=True,fontsize=self.fontsize_colorbar)
648
+
649
+ plt.setp(cntr.labelTexts, path_effects=[
650
+ patheffects.withStroke(linewidth=2, foreground="w")])
651
+
652
+
653
+ def draw_ppi(self,fieldname='reflectivity',tilt=0,colorfile=None,**kwargs):
654
+ cmapdic = parse_pro(colorfile)
655
+ if not isinstance(fieldname,str):
656
+ print('fieldname should be string')
657
+ return False
658
+ if not isinstance(tilt,int):
659
+ print('tilt should be int and >=0')
660
+ return False
661
+
662
+ self.display.plot_ppi_map(fieldname, tilt,cmap=cmapdic['cmap'],gatefilter=self.gatefilter_ref,
663
+ min_lon=self.wlon, max_lon=self.elon, norm=cmapdic['norm'],ax=self.ax1,
664
+ min_lat=self.slat, max_lat=self.nlat,lon_lines=[-110,],lat_lines=[-90,],title_flag=False,
665
+ fig=self.fig, lat_0=self.g_rad_lat,colorbar_flag=False,
666
+ lon_0=self.g_rad_lon,**kwargs)
667
+
668
+ def draw_wind_barb(self,zorder=1):
669
+ # 画风场
670
+ # filepath_minute='temp/backup_aws_minute'
671
+ # filename_aws='surface_aws_20210720_1800.csv'
672
+ if self.aws_min_file_name is None:
673
+ print('warning: aws_min_file_name is None!')
674
+ return False
675
+ if not os.path.exists(self.aws_min_file_path + os.sep + self.aws_min_file_name):
676
+ print(self.aws_min_file_path + os.sep + self.aws_min_file_name + ' does not exists!')
677
+ return False
678
+
679
+ awsdata = pd.read_csv(self.aws_min_file_path + os.sep + self.aws_min_file_name,encoding='GBK')
680
+
681
+ aws_lats=awsdata['Lat'].values
682
+ aws_lons=awsdata['Lon'].values
683
+ aws_2minspd=awsdata['WIN_S_Avg_2mi'].values
684
+ aws_2mindir=awsdata['WIN_D_Avg_2mi'].values
685
+ u,v=wind_components(aws_2minspd*units('m/s'),aws_2mindir*units.deg)
686
+ for nn in range(len(aws_lats)):
687
+ if aws_2minspd[nn] > 999000 or aws_2mindir[nn] > 999000 or aws_2minspd[nn] < 1:
688
+ continue
689
+ u,v=wind_components(float(2)*units('m/s'),int(aws_2mindir[nn])*units.deg)
690
+ plt.barbs(aws_lons[nn],aws_lats[nn],u.magnitude*2.5,v.magnitude*2.5,length=5,barbcolor='black',linewidth=2,zorder=zorder)
691
+ plt.barbs(aws_lons[nn],aws_lats[nn],u.magnitude*2.5,v.magnitude*2.5,length=5,barbcolor='white',linewidth=1,zorder=zorder)
692
+
693
+
694
+ def draw_wind_quiver(self,zorder=1):
695
+
696
+ if self.aws_min_file_name is None:
697
+ print('warning: aws_min_file_name is None!')
698
+ return False
699
+ if not os.path.exists(self.aws_min_file_path + os.sep + self.aws_min_file_name):
700
+ print(self.aws_min_file_path + os.sep + self.aws_min_file_name + ' does not exists!')
701
+ return False
702
+
703
+ awsdata = pd.read_csv(self.aws_min_file_path + os.sep + self.aws_min_file_name,encoding='GBK')
704
+
705
+ aws_lats=awsdata['Lat'].values
706
+ aws_lons=awsdata['Lon'].values
707
+ aws_2minspd=awsdata['WIN_S_Avg_2mi'].values
708
+ aws_2mindir=awsdata['WIN_D_Avg_2mi'].values
709
+ u,v=wind_components(aws_2minspd*units('m/s'),aws_2mindir*units.deg)
710
+ for nn in range(len(aws_lats)):
711
+ if aws_2minspd[nn] > 999000 or aws_2mindir[nn] > 999000 or aws_2minspd[nn] < 1:
712
+ continue
713
+ u,v=wind_components(float(2)*units('m/s'),int(aws_2mindir[nn])*units.deg)
714
+
715
+ self.ax1.quiver(aws_lons[nn],aws_lats[nn],u.magnitude,v.magnitude,width=0.003,minshaft=1,scale=60,facecolor=[0,0,0],
716
+ path_effects=[path_effects.Stroke(linewidth=0.5, foreground='white'),path_effects.Normal()],label='地面2分钟平均风',
717
+ zorder=zorder)#
718
+
719
+
720
+ def draw_pre_1h(self,):
721
+ # 叠加1小时降水场
722
+ # filepath_hour = 'temp/backup_aws_hourly'
723
+ # filename_hour = 'surface_aws_hourly_20210720_1000.csv'
724
+
725
+ # 方式2:从文件读取数据
726
+ awsdata_hourly = pd.read_csv(self.aws_hour_file_path + os.sep + self.aws_hour_file_name,encoding='GBK')
727
+ awsdata_hourly = awsdata_hourly.sort_values(by='PRE_1h')
728
+ pre_1h = awsdata_hourly['PRE_1h'].values
729
+ pre_lat = awsdata_hourly['Lat'].values
730
+ pre_lon = awsdata_hourly['Lon'].values
731
+
732
+ geodetic_transform = ccrs.Geodetic()._as_mpl_transform(self.ax1)
733
+ text_transform = offset_copy(geodetic_transform, units='dots', x=-5)
734
+ for nn in range(len(pre_1h)):
735
+ if pre_1h[nn] > 1000 or pre_1h[nn] < self.thred_pre1h:
736
+ continue
737
+ precolor=[1,1,1]
738
+ # print(pre_1h[nn])
739
+ if pre_1h[nn] >= 50 and pre_1h[nn] < 80:
740
+ precolor=[0,1,1]
741
+ elif pre_1h[nn] >= 80 and pre_1h[nn] < 100:
742
+ precolor=[1,1,0]
743
+ elif pre_1h[nn] >= 100:
744
+ precolor=[1,0,1]
745
+ self.ax1.text(pre_lon[nn],pre_lat[nn],'%d'%(int(pre_1h[nn])), clip_on=True,
746
+ verticalalignment='center', horizontalalignment='right',
747
+ transform=text_transform, fontproperties=self.font_colorbar, color=precolor,
748
+ path_effects=[path_effects.Stroke(linewidth=1, foreground='black'),path_effects.Normal()])
749
+
750
+ def draw_colorbar(self,colorfile,tickstep=5,orientation='vertical',cb_ratio=0.618):
751
+ # 画色标
752
+
753
+ # 水平色标
754
+ if orientation == 'horizontal':
755
+ # cbar_axes = [0.01, 0.01, 0.95, 0.04]
756
+ cbar_axes = [self.map_panel_axes[0],self.map_panel_axes[1]+0.01+self.map_panel_axes[3],self.map_panel_axes[2]*0.618,0.03]
757
+
758
+ ax2 = self.fig.add_axes(cbar_axes)
759
+ ax2.set_axis_off()
760
+ cmapdic = parse_pro(colorfile)
761
+ cbar = ColorbarBase(ax2, orientation="horizontal", norm=cmapdic['norm'], cmap=cmapdic['cmap'],extend='both')
762
+ cbar.set_ticks([])
763
+ trans = transforms.blended_transform_factory(ax2.transData, ax2.transAxes)
764
+ tick_poss=np.arange(cmapdic['norm'].vmin, cmapdic['norm'].vmax, tickstep)
765
+ for tick_pos in tick_poss:
766
+ ax2.vlines(tick_pos, 0, 0.2, transform=trans, color="black")
767
+ ax2.vlines(tick_pos, 0.85, 1, transform=trans, color="black")
768
+ # bbox=dict(facecolor="white", alpha=0.8, edgecolor="black")
769
+ # ax2.text(tick_pos, 0.5, str(int(tick_pos)),color=[1,1,1],path_effects=[path_effects.Stroke(linewidth=1, foreground='black'),path_effects.Normal()],
770
+ # va="center", ha="center", transform=trans, fontsize = self.fontsize1)
771
+ ax2.text(tick_pos, 1.4, str(int(tick_pos)),va="center", ha="center", transform=trans, fontsize = self.fontsize_colorbar)
772
+ # ax2.text(1.02, 0.5, cmapdic['units'], transform=ax2.transAxes,va="center", ha="center",
773
+ # color=[1,1,1],path_effects=[path_effects.Stroke(linewidth=1, foreground='black'),path_effects.Normal()],fontsize = self.fontsize_colorbar)
774
+ ax2.text(1.02, 0.5, cmapdic['units'], transform=ax2.transAxes,va="center", ha="center",fontsize = self.fontsize_colorbar)
775
+
776
+
777
+ # 垂直色标
778
+ if orientation == 'vertical':
779
+ # cbar_axes = [self.map_panel_axes[0]+ self.map_panel_axes[2] + 0.01,self.map_panel_axes[1],0.03,self.map_panel_axes[3]]
780
+ ax_pos = self.ax1.get_position().bounds
781
+ cbar_axes = [ax_pos[0]+ ax_pos[2]+0.01,(ax_pos[1]+ax_pos[1]+ax_pos[3])/2-ax_pos[3]*cb_ratio/2,0.02,ax_pos[3]*cb_ratio]
782
+ cb_ax = self.fig.add_axes(cbar_axes)
783
+ colordata = parse_pro(colorfile)
784
+
785
+ cbar = ColorbarBase(cb_ax, orientation=orientation, norm=colordata['norm'], cmap=colordata['cmap'],extend='both')
786
+ cbar.set_ticks([])
787
+ # cb_ax.axis('tight')
788
+
789
+ trans = transforms.blended_transform_factory(cb_ax.transData, cb_ax.transAxes)
790
+ tick_poss=np.arange(colordata['norm'].vmin, colordata['norm'].vmax, tickstep)
791
+ xrange = colordata['norm'].vmax - colordata['norm'].vmin
792
+
793
+ for tick_pos in tick_poss:
794
+ cb_ax.hlines(tick_pos, colordata['norm'].vmin, colordata['norm'].vmin + 0.3*xrange, color="black",linewidth=0.5)
795
+ cb_ax.hlines(tick_pos, colordata['norm'].vmin + 0.7*xrange, colordata['norm'].vmax, color="black",linewidth=0.5)
796
+
797
+ # cb_ax.text(1.02,tick_pos, str(int(tick_pos)),color=[1,1,1],
798
+ # path_effects=[path_effects.Stroke(linewidth=self.stroke_line_width, foreground='black'),
799
+ # path_effects.Normal()],
800
+ # va="center", ha="left",font=self.font_colorbar)
801
+
802
+ cb_ax.text(1.04,tick_pos, str(int(tick_pos)),va="center", ha="left",fontsize=5) # font=self.font_colorbar
803
+
804
+ cb_ax.text(1.85, 1.035, colordata['units'], transform=cb_ax.transAxes,va="center", ha="center", fontsize=5 ) # ,font=self.font_colorbar
805
+ # color=[1,1,1],path_effects=[path_effects.Stroke(linewidth=self.stroke_line_width, foreground='black'),path_effects.Normal()],
806
+
807
+
808
+ def draw_gisinfo(self,):
809
+ geodetic_transform = ccrs.Geodetic()._as_mpl_transform(self.ax1)
810
+ text_transform = offset_copy(geodetic_transform, units='dots', x=-5)
811
+ aa = (np.array(self.gis_lats)<self.nlat) & (np.array(self.gis_lats) > self.slat)
812
+ bb = (np.array(self.gis_lons)<self.elon) & (np.array(self.gis_lons) > self.wlon)
813
+ cc = aa & bb
814
+ # cc = cc.values
815
+
816
+ alltxt=[]
817
+ for nn in range(len(self.gis_name)):
818
+ if not cc[nn]:
819
+ continue
820
+ curlat = self.gis_lats[nn]
821
+ curlon = self.gis_lons[nn]
822
+ self.ax1.plot(curlon, curlat, marker='o', color=[0.2,0.2,0.2], linestyle='None',
823
+ markersize=1, alpha=0.8, transform=ccrs.PlateCarree())
824
+ txt_lon = curlon
825
+ txt_lat = curlat
826
+ if self.gis_name[nn] == '农博园':
827
+ txt_lon = curlon + 0.05
828
+ txt_lat = curlat + 0.01
829
+ elif self.gis_name[nn] == '吉林农大':
830
+ txt_lon = curlon + 0.06
831
+ txt_lat = curlat - 0.015
832
+ texts = self.ax1.text(txt_lon, txt_lat, self.gis_name[nn], clip_on=True,
833
+ verticalalignment='center', horizontalalignment='right',
834
+ transform=text_transform, fontproperties=self.font_gis, color='white',
835
+ path_effects=[path_effects.Stroke(linewidth=1, foreground='black'),path_effects.Normal()])
836
+ # alltxt.append(texts)
837
+ # adjust_text(alltxt)
838
+
839
+ def add_china_map_2cartopy(self, ax, name='province', facecolor='none',
840
+ edgecolor='c', lw=1, **kwargs):
841
+ """
842
+ Draw china boundary on cartopy map.
843
+
844
+ :param ax: matplotlib axes instance.
845
+ :param name: map name.
846
+ :param facecolor: fill color, default is none.
847
+ :param edgecolor: edge color.
848
+ :param lw: line width.
849
+ :return: None
850
+ """
851
+
852
+ # map name
853
+ names = {'nation': "bou1_4p", 'province': "bou2_4p",
854
+ 'county': "BOUNT_poly", 'river': "hyd1_4l",
855
+ 'river_high': "hyd2_4l"}
856
+
857
+ # get shape filename
858
+ shpfile = "./resources/maps/" + names[name] + ".shp"
859
+
860
+ # add map
861
+ ax.add_geometries(
862
+ Reader(shpfile).geometries(), ccrs.PlateCarree(),
863
+ path_effects=[path_effects.Stroke(linewidth=lw+0.2, foreground='white'),path_effects.Normal()],
864
+ facecolor=facecolor, edgecolor=edgecolor, lw=lw, **kwargs)
865
+
866
+ def draw_basemap(self,):
867
+ # Setting projection and ploting the second tilt
868
+ projection = ccrs.PlateCarree()
869
+ # projection = ccrs.LambertConformal(central_latitude=radar.latitude['data'][0],
870
+ # central_longitude=radar.longitude['data'][0])
871
+ # figsize=(4,3)
872
+ self.fig = plt.figure(figsize=(self.paintsize_x,self.paintsize_y))
873
+ # DPI = 100
874
+ # fig.set_size_inches(800.0/float(DPI),600.0/float(DPI))
875
+
876
+ self.map_panel_axes = [0.12, 0.1, .76, .8]
877
+ # map_panel_axes = [0.01, 0.06, 0.98, 0.88]
878
+ self.ax1 = self.fig.add_axes(self.map_panel_axes, projection=projection)
879
+ pass
880
+
881
+ def add_chinamap(self,):
882
+ self.add_china_map_2cartopy(self.ax1, name='county', facecolor='none',edgecolor=self.mapcolor, lw=self.linewidth_map)
883
+ # self.add_china_map_2cartopy(self.ax1, name='county', facecolor='none',edgecolor=[0.8,0.8,0.8], lw=1)
884
+
885
+
886
+ def draw_title(self,titlestr='XX雷达0.5度仰角径向速度'):
887
+ if not self.bdraw_title_ppi:
888
+ return None
889
+
890
+ tstr=''
891
+ if self.voltime is None:
892
+ tstr = self.timestr
893
+ else:
894
+ tstr = self.voltime
895
+
896
+ plt.title('%s(%s BJT)'%(titlestr,tstr),fontproperties=self.font_title,loc='right',verticalalignment='top')
897
+
898
+ def crs_finish_save(self,bshow=False,subdir='',add_str='',):
899
+ # self.crs_ax.axis('tight')
900
+ # self.crs_ax.set_xlim([0,150])
901
+
902
+ try:
903
+ if not os.path.exists(self.picpath + os.sep + subdir):
904
+ os.makedirs(self.picpath + os.sep + subdir)
905
+ except:
906
+ pass
907
+ if self.pic_format=='ps':
908
+ plt.savefig(self.picpath + os.sep + subdir + os.sep + self.timestr + '.' + add_str + '.' + self.pic_format,dpi=self.dpi)
909
+ else:
910
+ plt.savefig(self.picpath + os.sep + subdir + os.sep + self.timestr + '.' + add_str + '.' + self.pic_format,dpi=self.dpi,bbox_inches='tight')
911
+ # plt.savefig(self.picpath + os.sep + subdir + os.sep + self.timestr + add_str + '.eps',dpi=self.dpi)
912
+ print('image saved: ' + self.picpath + os.sep + subdir + os.sep + self.timestr + '.' + add_str + '.' + self.pic_format)
913
+ if bshow:
914
+ plt.show()
915
+
916
+ plt.close('all')
917
+
918
+ def finish_save(self,bshow=False,subdir='',):
919
+ self.ax1.axis('tight')
920
+ self.ax1.set_xlim([self.wlon,self.elon])
921
+ self.ax1.set_ylim([self.slat,self.nlat])
922
+
923
+ if self.elon - self.wlon > 5:
924
+ lon_step = 1
925
+ elif self.elon - self.wlon > 1:
926
+ lon_step = 0.5
927
+ else:
928
+ lon_step = 0.2
929
+
930
+ if self.nlat - self.slat > 5:
931
+ lat_step = 1
932
+ elif self.nlat - self.slat > 1:
933
+ lat_step = 0.5
934
+ else:
935
+ lat_step = 0.2
936
+ self.ax1.xaxis.set_major_formatter(major_formatter_lon)
937
+ self.ax1.yaxis.set_major_formatter(major_formatter_lat)
938
+ self.ax1.set_xticks(np.arange(self.wlon,self.elon,lon_step))
939
+ self.ax1.set_yticks(np.arange(self.slat,self.nlat,lat_step))
940
+
941
+ self.ax1.minorticks_on()
942
+
943
+ # self.ax1.legend(loc='upper right')
944
+ if not os.path.exists(self.picpath + os.sep + subdir): os.makedirs(self.picpath + os.sep + subdir)
945
+ if self.pic_format=='ps':
946
+ plt.savefig(self.picpath + os.sep + subdir + os.sep + self.timestr + '.' + self.pic_format,dpi=self.dpi)
947
+ else:
948
+ plt.savefig(self.picpath + os.sep + subdir + os.sep + self.timestr + '.' + self.pic_format,dpi=self.dpi,bbox_inches='tight')
949
+ print('image saved: ' + self.picpath + os.sep + subdir + os.sep + self.timestr + '.' + self.pic_format)
950
+ if bshow:
951
+ plt.show()
952
+
953
+ plt.close('all')
954
+
955
+ def draw_vel_pre(self,subdir='径向速度+当前小时降水',tilt=1):
956
+ # check
957
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
958
+ # print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
959
+ return False
960
+ self.draw_basemap()
961
+ self.draw_gisinfo()
962
+ self.draw_ppi(fieldname='velocity',tilt=tilt,colorfile=self.vel_colorfile)
963
+ self.draw_pre_1h()
964
+ self.add_chinamap()
965
+ ele=np.mean(self.radar.get_elevation(tilt))
966
+ self.draw_title('%s雷达%.1f度%s'%(self.radarname,ele, subdir))
967
+ self.draw_colorbar(colorfile=self.vel_colorfile)
968
+ self.finish_save(subdir=subdir)
969
+
970
+ def draw_ref_alone(self,subdir='基本反射率',tilt=0,thred=-5,):
971
+ # check
972
+ if self.radar is None:
973
+ return False
974
+ self.gatefilter_ref = pyart.correct.GateFilter(self.radar)
975
+ self.gatefilter_ref.exclude_below('reflectivity', thred, exclude_masked=True, op='or', inclusive=False)
976
+
977
+ ele=np.mean(self.radar.get_elevation(tilt))
978
+ subdir='%.1f度仰角%s'%(ele,subdir)
979
+ if not self.breplace and os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
980
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
981
+ return False
982
+ self.draw_basemap()
983
+ self.draw_gisinfo()
984
+ self.draw_ppi(fieldname='reflectivity',tilt=tilt,colorfile=self.ref_colorfile)
985
+ self.add_chinamap()
986
+ self.draw_title(subdir)
987
+ self.draw_colorbar(colorfile=self.ref_colorfile,orientation='vertical')
988
+ self.add_crs_line(ax=self.ax1)
989
+
990
+ self.finish_save(subdir=subdir,)
991
+
992
+ # 画相关系数,偏振量
993
+ def draw_cc_alone(self,subdir='相关系数',tilt=0,thred=-5,):
994
+ # check
995
+ if self.radar is None:
996
+ return False
997
+ self.gatefilter_ref = pyart.correct.GateFilter(self.radar)
998
+ self.gatefilter_ref.exclude_below('cross_correlation_ratio', thred, exclude_masked=True, op='or', inclusive=False)
999
+
1000
+ ele=np.mean(self.radar.get_elevation(tilt))
1001
+ subdir='%.1f度仰角%s'%(ele,subdir)
1002
+ if not self.breplace and os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1003
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1004
+ return False
1005
+ self.draw_basemap()
1006
+ self.draw_gisinfo()
1007
+ self.draw_ppi(fieldname='cross_correlation_ratio',tilt=tilt,colorfile=self.ref_colorfile)
1008
+ self.add_chinamap()
1009
+ self.draw_title(subdir)
1010
+ self.draw_colorbar(colorfile=self.cc_colorfile,orientation='vertical')
1011
+ self.add_crs_line(ax=self.ax1)
1012
+
1013
+ self.finish_save(subdir=subdir,)
1014
+
1015
+
1016
+ # 画差分反射率,偏振量
1017
+ def draw_zdr_alone(self,subdir='差分反射率',tilt=0,thred=-5,):
1018
+ # check
1019
+ if self.radar is None:
1020
+ return False
1021
+ self.gatefilter_ref = pyart.correct.GateFilter(self.radar)
1022
+ self.gatefilter_ref.exclude_below('cross_correlation_ratio', thred, exclude_masked=True, op='or', inclusive=False)
1023
+
1024
+ ele=np.mean(self.radar.get_elevation(tilt))
1025
+ subdir='%.1f度仰角%s'%(ele,subdir)
1026
+ if not self.breplace and os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1027
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1028
+ return False
1029
+ self.draw_basemap()
1030
+ self.draw_gisinfo()
1031
+ self.draw_ppi(fieldname='cross_correlation_ratio',tilt=tilt,colorfile=self.ref_colorfile)
1032
+ self.add_chinamap()
1033
+ self.draw_title(subdir)
1034
+ self.draw_colorbar(colorfile=self.zdr_colorfile,orientation='vertical')
1035
+ self.add_crs_line(ax=self.ax1)
1036
+
1037
+ self.finish_save(subdir=subdir,)
1038
+
1039
+ def draw_vel_alone(self,subdir='径向速度',tilt=0,format='png'):
1040
+ # check
1041
+ if self.radar is None:
1042
+ return False
1043
+ ele=np.mean(self.radar.get_elevation(tilt))
1044
+ subdir='%.1f度仰角%s'%(ele,subdir)
1045
+
1046
+ if not self.breplace and os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.' + format):
1047
+ print(self.picpath + os.sep + subdir + self.timestr + '.' + format + ' already exists!')
1048
+ return False
1049
+ self.draw_basemap()
1050
+ self.draw_gisinfo()
1051
+ self.draw_ppi(fieldname='velocity',tilt=tilt,colorfile=self.vel_colorfile)
1052
+ self.add_chinamap()
1053
+ self.draw_title(subdir)
1054
+ self.add_crs_line(ax=self.ax1)
1055
+ self.draw_colorbar(colorfile=self.vel_colorfile)
1056
+ self.finish_save(subdir=subdir,)
1057
+
1058
+ def draw_vel_wind_barb(self,subdir='径向速度+地面自动站风场',tilt=1):
1059
+ # check
1060
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1061
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1062
+ return False
1063
+ self.draw_basemap()
1064
+ self.draw_gisinfo()
1065
+ self.draw_ppi(fieldname='velocity',tilt=tilt,colorfile=self.vel_colorfile)
1066
+ self.add_chinamap()
1067
+ self.draw_wind_barb()
1068
+ ele=np.mean(self.radar.get_elevation(tilt))
1069
+ self.draw_title('%s雷达%.1f度%s'%(self.radarname,ele, subdir))
1070
+ self.draw_colorbar(colorfile=self.vel_colorfile)
1071
+ self.finish_save(subdir=subdir)
1072
+
1073
+ def draw_vel_wind_quiver(self,subdir='径向速度+地面流场',tilt=1):
1074
+ # check
1075
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1076
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1077
+ return False
1078
+ self.draw_basemap()
1079
+ self.draw_gisinfo()
1080
+ self.draw_ppi(fieldname='velocity',tilt=tilt,colorfile=self.vel_colorfile)
1081
+ self.add_chinamap()
1082
+ self.draw_wind_quiver()
1083
+ ele=np.mean(self.radar.get_elevation(tilt))
1084
+ self.draw_title('%s雷达%.1f度%s'%(self.radarname,ele, subdir))
1085
+ self.draw_colorbar(colorfile=self.vel_colorfile)
1086
+ self.finish_save(subdir=subdir)
1087
+
1088
+ def draw_ref_pre(self,subdir='基本反射率+当前小时降水',tilt=0):
1089
+ # check
1090
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1091
+ # print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1092
+ return False
1093
+ self.draw_basemap()
1094
+ self.draw_gisinfo()
1095
+ self.draw_ppi(fieldname='reflectivity',tilt=tilt,colorfile=self.ref_colorfile)
1096
+ self.draw_pre_1h()
1097
+ self.add_chinamap()
1098
+ ele=np.mean(self.radar.get_elevation(tilt))
1099
+ self.draw_title('%s雷达%.1f度%s'%(self.radarname,ele, subdir))
1100
+ self.draw_colorbar(colorfile=self.ref_colorfile)
1101
+ self.finish_save(subdir=subdir)
1102
+
1103
+ def draw_cref_pre(self,subdir='组合反射率+当前小时降水'):
1104
+ # check
1105
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1106
+ # print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1107
+ return False
1108
+ self.draw_basemap()
1109
+ self.draw_gisinfo()
1110
+ self.draw_cref()
1111
+ self.draw_pre_1h()
1112
+ self.add_chinamap()
1113
+ self.draw_title('组合反射率因子+当前小时降水量')
1114
+ self.draw_colorbar(colorfile=self.ref_colorfile)
1115
+ self.finish_save(subdir=subdir)
1116
+
1117
+ def draw_cref_wind_barb(self,subdir='组合反射率+地面自动站风场'):
1118
+ # check
1119
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1120
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1121
+ return False
1122
+ self.draw_basemap()
1123
+ self.draw_gisinfo()
1124
+ self.draw_cref()
1125
+ self.add_chinamap()
1126
+ self.draw_wind_barb()
1127
+ self.draw_title(subdir)
1128
+ self.draw_colorbar(colorfile=self.ref_colorfile)
1129
+ self.finish_save(subdir=subdir)
1130
+
1131
+ def draw_cref_wind_quiver(self,subdir='组合反射率+地面流场'):
1132
+ # check
1133
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1134
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1135
+ return False
1136
+ self.draw_basemap()
1137
+ self.draw_gisinfo()
1138
+ self.draw_cref()
1139
+ self.add_chinamap()
1140
+ self.draw_wind_quiver()
1141
+ self.draw_title(subdir)
1142
+ self.draw_colorbar(colorfile=self.ref_colorfile)
1143
+ self.finish_save(subdir=subdir)
1144
+
1145
+ def draw_cref_pre_wind_barb(self,subdir='组合反射率+地面自动站风场+当前小时降水'):
1146
+ # check
1147
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1148
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1149
+ return False
1150
+
1151
+ self.draw_basemap()
1152
+ self.draw_gisinfo()
1153
+ self.draw_cref()
1154
+ self.draw_wind_barb()
1155
+ self.draw_pre_1h()
1156
+ self.add_chinamap()
1157
+ self.draw_title(subdir)
1158
+ self.draw_colorbar(colorfile=self.ref_colorfile)
1159
+ self.finish_save(subdir=subdir)
1160
+
1161
+
1162
+ def draw_ref_wind_barb_vortex(self,subdir='基本反射率+地面自动站风场+涡度场(等值线)',tilt=0):
1163
+ # check
1164
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1165
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1166
+ return False
1167
+ self.draw_basemap()
1168
+ self.draw_gisinfo()
1169
+ self.draw_ppi(fieldname='reflectivity',tilt=tilt,colorfile=self.ref_colorfile)
1170
+ self.draw_vortex(zorder=2)
1171
+ self.add_chinamap()
1172
+ self.draw_wind_barb(zorder=10)
1173
+ ele=np.mean(self.radar.get_elevation(tilt))
1174
+ self.draw_title('%s雷达%.1f度%s'%(self.radarname,ele, subdir))
1175
+ self.draw_colorbar(colorfile=self.ref_colorfile)
1176
+ self.finish_save(subdir=subdir)
1177
+
1178
+ def draw_ref_wind_divergence(self,subdir='基本反射率+地面自动站风场+散度(等值线)',tilt=0,type='quiver'):
1179
+ # check
1180
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1181
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1182
+ return False
1183
+ self.draw_basemap()
1184
+ self.draw_gisinfo()
1185
+ self.draw_ppi(fieldname='reflectivity',tilt=tilt,colorfile=self.ref_colorfile)
1186
+ self.draw_divergence(zorder=2)
1187
+ self.add_chinamap()
1188
+ if type == 'quiver':
1189
+ self.draw_wind_quiver(zorder=10)
1190
+ elif type == 'barb':
1191
+ self.draw_wind_barb(zorder=10)
1192
+ ele=np.mean(self.radar.get_elevation(tilt))
1193
+ self.draw_title('%s雷达%.1f度%s'%(self.radarname,ele, subdir))
1194
+ self.draw_colorbar(colorfile=self.ref_colorfile)
1195
+ self.finish_save(subdir=subdir)
1196
+
1197
+ def draw_ref_wind_barb_temperature(self,subdir='基本反射率+地面自动站风场+温度场(等值线)',tilt=0):
1198
+ # check
1199
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1200
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1201
+ return False
1202
+ self.draw_basemap()
1203
+ self.draw_gisinfo()
1204
+ self.draw_ppi(fieldname='reflectivity',tilt=tilt,colorfile=self.ref_colorfile)
1205
+ self.draw_temperature(zorder=2)
1206
+ self.add_chinamap()
1207
+ self.draw_wind_barb(zorder=10)
1208
+ ele=np.mean(self.radar.get_elevation(tilt))
1209
+ self.draw_title('%s雷达%.1f度%s'%(self.radarname,ele, subdir))
1210
+ self.draw_colorbar(colorfile=self.ref_colorfile)
1211
+ self.finish_save(subdir=subdir)
1212
+
1213
+ def draw_ref_wind_barb_dewpoint(self,subdir='基本反射率+地面自动站风场+露点场(等值线)',tilt=0):
1214
+ # check
1215
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1216
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1217
+ return False
1218
+ self.draw_basemap()
1219
+ self.draw_gisinfo()
1220
+ self.draw_ppi(fieldname='reflectivity',tilt=tilt,colorfile=self.ref_colorfile)
1221
+ self.draw_drewpoint(zorder=2)
1222
+ self.add_chinamap()
1223
+ self.draw_wind_barb(zorder=10)
1224
+ ele=np.mean(self.radar.get_elevation(tilt))
1225
+ self.draw_title('%s雷达%.1f度%s'%(self.radarname,ele, subdir))
1226
+ self.draw_colorbar(colorfile=self.ref_colorfile)
1227
+ self.finish_save(subdir=subdir)
1228
+
1229
+
1230
+ def draw_ref_pre_wind(self,subdir='基本反射率+地面自动站风场+当前小时降水',type='barb',tilt=0):
1231
+ # type == barb or quiver
1232
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1233
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1234
+ return False
1235
+ self.draw_basemap()
1236
+ self.draw_gisinfo()
1237
+ self.draw_ppi(fieldname='reflectivity',tilt=tilt,colorfile=self.ref_colorfile)
1238
+ if type == 'barb':
1239
+ self.draw_wind_barb()
1240
+ elif type == 'quiver':
1241
+ self.draw_wind_quiver()
1242
+ self.draw_pre_1h()
1243
+ self.add_chinamap()
1244
+ ele=np.mean(self.radar.get_elevation(tilt))
1245
+ self.draw_title('%s雷达%.1f度%s'%(self.radarname,ele, subdir))
1246
+ self.draw_colorbar(colorfile=self.ref_colorfile)
1247
+ self.finish_save(subdir=subdir)
1248
+
1249
+ def draw_ref_wind(self,subdir='基本反射率+地面自动站风场',type='barb',tilt=0):
1250
+ # type == barb or quiver
1251
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.png'):
1252
+ print(self.picpath + os.sep + subdir + self.timestr + '.png' + ' already exists!')
1253
+ return False
1254
+ self.draw_basemap()
1255
+ self.draw_gisinfo()
1256
+ self.draw_ppi(fieldname='reflectivity',tilt=tilt,colorfile=self.ref_colorfile)
1257
+ if type == 'barb':
1258
+ self.draw_wind_barb()
1259
+ elif type == 'quiver':
1260
+ self.draw_wind_quiver()
1261
+ self.add_chinamap()
1262
+ ele=np.mean(self.radar.get_elevation(tilt))
1263
+ self.draw_title('%s雷达%.1f度%s'%(self.radarname,ele, subdir))
1264
+ self.draw_colorbar(colorfile=self.ref_colorfile)
1265
+ self.finish_save(subdir=subdir)
1266
+
1267
+ def draw_delta_t(self,zorder=2):
1268
+
1269
+ # 叠加1小时变温
1270
+ # filepath_minute='temp/backup_aws_minute'
1271
+ # filename_aws='surface_aws_20210720_1800.csv'
1272
+ if self.aws_min_delta_t_file_name is None:
1273
+ print('warning: aws_min_delta_t_file_name is None!')
1274
+ return False
1275
+ if not os.path.exists(self.aws_min_delta_t_file_path + os.sep + self.aws_min_delta_t_file_name):
1276
+ print(self.aws_min_delta_t_file_path + os.sep + self.aws_min_delta_t_file_name + ' does not exists!')
1277
+ return False
1278
+
1279
+ delta_t_data = xr.open_dataset(self.aws_min_delta_t_file_path + os.sep + self.aws_min_delta_t_file_name)
1280
+
1281
+
1282
+ levels = list(np.arange(delta_t_data.attrs['sta_minvalue'], delta_t_data.attrs['sta_maxvalue'], 0.2))
1283
+
1284
+ cntr = self.ax1.contour(delta_t_data.lon.values,delta_t_data.lat.values,delta_t_data.t2m_delta_1hr.values.T,
1285
+ levels=levels,colors=self.contour_color,zorder=zorder,linewidths=self.linewidth_cntr)
1286
+
1287
+ plt.setp(cntr.collections, path_effects=[
1288
+ patheffects.withStroke(linewidth=self.linewidth_cntr, foreground="w")])
1289
+ clbls = self.ax1.clabel(cntr,fmt="%2.1f",use_clabeltext=True,fontsize=self.fontsize_colorbar)
1290
+
1291
+ plt.setp(cntr.labelTexts, path_effects=[
1292
+ patheffects.withStroke(linewidth=self.linewidth_cntr, foreground="w")])
1293
+
1294
+ def draw_delta_p(self,zorder=2):
1295
+
1296
+ # 叠加1小时变压
1297
+ # filepath_minute='temp/backup_aws_minute'
1298
+ # filename_aws='surface_aws_20210720_1800.csv'
1299
+ if self.aws_min_delta_p_file_name is None:
1300
+ print('warning: aws_min_delta_p_file_name is None!')
1301
+ return False
1302
+ if not os.path.exists(self.aws_min_delta_p_file_path + os.sep + self.aws_min_delta_p_file_name):
1303
+ print(self.aws_min_delta_p_file_path + os.sep + self.aws_min_delta_p_file_name + ' does not exists!')
1304
+ return False
1305
+
1306
+ delta_p_data = xr.open_dataset(self.aws_min_delta_p_file_path + os.sep + self.aws_min_delta_p_file_name)
1307
+
1308
+
1309
+ levels = list(np.arange(delta_p_data.attrs['sta_minvalue'], delta_p_data.attrs['sta_maxvalue'], 0.1))
1310
+
1311
+ cntr = self.ax1.contour(delta_p_data.lon.values,delta_p_data.lat.values,delta_p_data.sprs2m_delta_1hr.values.T,
1312
+ levels=levels,colors=self.contour_color,zorder=zorder,linewidths=self.linewidth_cntr,label='1小时变压')
1313
+
1314
+ plt.setp(cntr.collections, path_effects=[
1315
+ patheffects.withStroke(linewidth=self.linewidth_cntr, foreground="w")])
1316
+
1317
+ clbls = self.ax1.clabel(cntr,fmt="%2.1f",use_clabeltext=True,fontsize=self.fontsize_colorbar,inline=True)
1318
+
1319
+ plt.setp(cntr.labelTexts, path_effects=[
1320
+ patheffects.withStroke(linewidth=self.linewidth_cntr, foreground="w")])
1321
+ return cntr
1322
+
1323
+
1324
+ def draw_topo(self,):
1325
+ # 读取地形数据
1326
+ filename = './resources/topo/topo_china.nc'
1327
+ # filename = 'resources/topo/china_dem_30m.nc'
1328
+ basetopo = xr.open_dataset(filename)
1329
+ #根据经纬度范围获取区域内的地形高度最大最小值
1330
+ topo = basetopo.sel(Longitude=slice(self.wlon,self.elon),Latitude=slice(self.slat,self.nlat))
1331
+ # topo = basetopo.sel(lon=slice(self.wlon,self.elon),lat=slice(self.slat,self.nlat))
1332
+ topo_min = float(topo.min().topo.values)
1333
+ topo_max = float(topo.max().topo.values)
1334
+ # self.ax1.pcolormesh(topo['lon'].values,topo['lat'].values,topo['topo'],vmin=300,vmax=1000,cmap='pyart_Gray5')# ,levels=[250,500,750,1000],
1335
+ self.ax1.pcolormesh(topo['Longitude'].values,topo['Latitude'].values,topo['topo'],vmin=300,vmax=1000,cmap='pyart_Gray5')# ,levels=[250,500,750,1000],
1336
+
1337
+ # 叠加1小时变温
1338
+ def draw_ref_wind_delta_t(self,subdir='基本反射率+地面自动站风场+1小时变温(等值线)',tilt=0,type='quiver'):
1339
+ # check
1340
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + '.' + self.pic_format):
1341
+ print(self.picpath + os.sep + subdir + self.timestr + '.' + self.pic_format + ' already exists!')
1342
+ return False
1343
+ self.draw_basemap()
1344
+ self.draw_gisinfo()
1345
+ self.draw_topo()
1346
+ self.draw_ppi(fieldname='reflectivity',tilt=tilt,colorfile=self.ref_colorfile)
1347
+ # self.draw_divergence(zorder=2)
1348
+ self.draw_delta_t(zorder=2)
1349
+ self.add_chinamap()
1350
+ if type == 'quiver':
1351
+ self.draw_wind_quiver(zorder=10)
1352
+ elif type == 'barb':
1353
+ self.draw_wind_barb(zorder=10)
1354
+ ele=np.mean(self.radar.get_elevation(tilt))
1355
+ self.draw_title('%s雷达%.1f度%s'%(self.radarname,ele, subdir))
1356
+ self.draw_colorbar(colorfile=self.ref_colorfile)
1357
+ self.finish_save(subdir=subdir)
1358
+
1359
+ # 叠加1小时变压
1360
+ def draw_ref_wind_delta_p(self,subdir='基本反射率+地面自动站风场+1小时变压(等值线)',tilt=0,type='quiver'):
1361
+ # check
1362
+ if os.path.exists(self.picpath + os.sep + subdir + os.sep +self.timestr + + '.' + self.pic_format):
1363
+ print(self.picpath + os.sep + subdir + self.timestr + + '.' + self.pic_format + ' already exists!')
1364
+ return False
1365
+ self.draw_basemap()
1366
+ self.draw_gisinfo()
1367
+ self.draw_ppi(fieldname='reflectivity',tilt=tilt,colorfile=self.ref_colorfile)
1368
+ self.draw_delta_p(zorder=2)
1369
+
1370
+
1371
+ self.add_chinamap()
1372
+ if type == 'quiver':
1373
+ self.draw_wind_quiver(zorder=10)
1374
+ elif type == 'barb':
1375
+ self.draw_wind_barb(zorder=10)
1376
+ ele=np.mean(self.radar.get_elevation(tilt))
1377
+ self.draw_title('%s雷达%.1f度%s'%(self.radarname,ele, subdir))
1378
+ self.draw_colorbar(colorfile=self.ref_colorfile)
1379
+ self.finish_save(subdir=subdir)