metradar 0.1.2__py3-none-any.whl → 0.1.4__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.
@@ -0,0 +1,37 @@
1
+ Metadata-Version: 2.2
2
+ Name: metradar
3
+ Version: 0.1.4
4
+ Summary: radar data processing
5
+ Author-email: Wenjian Zhu <kevin2075@163.com>
6
+ Keywords: Weather,Radar
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Operating System :: Unix
11
+ Classifier: Operating System :: Microsoft
12
+ Classifier: Operating System :: MacOS
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Topic :: Scientific/Engineering
15
+ Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
16
+ Classifier: Topic :: Scientific/Engineering :: GIS
17
+ Classifier: Topic :: Scientific/Engineering :: Hydrology
18
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ Requires-Dist: numpy>=1.18
22
+ Requires-Dist: requests>=2.24.0
23
+ Requires-Dist: arm_pyart>=1.19.5
24
+ Requires-Dist: cartopy>=0.24.0
25
+ Requires-Dist: openpyxl>=3.1.5
26
+ Requires-Dist: pydda==1.2.0
27
+ Requires-Dist: tqdm>=4.67.0
28
+ Requires-Dist: wradlib>=2.4.0
29
+
30
+ <div align="center">
31
+
32
+ # Welcome to METRADAR
33
+
34
+ ## 🚀 Quick start
35
+ metradar provides an easy-to-use python interface to read, process and visualize weather radar data specially for chinese users.
36
+
37
+ It is still under test.
@@ -1,14 +1,9 @@
1
1
  metradar/__init__.py,sha256=ZVCYWH_GLhi0vIbCFFMJTzmReIpKmKMWLy0K-dreAF0,183
2
2
  metradar/cnrad_level2.py,sha256=vy4d-CCAigJGZrm-Dr3_NsmzSs1Tg_ufQvVSZSH57ic,44916
3
3
  metradar/comm_func.py,sha256=SByR9y5y9qdEcoDooSbEAN0Mxcw8QnPFN78n-s-INbg,4170
4
- metradar/construct_aws_refvpr_mainprog.py,sha256=CJgEZRt9Bcqj-KkiUnKfdTnz2CMG47rkJljnT6-4bWg,22205
5
- metradar/construct_aws_refvpr_mainprog_cams.py,sha256=9xCa5_PuqZxPEW-A-657D2-sQ7ZFRQYmlT387mWYWWY,12404
6
- metradar/construct_aws_refvpr_mainprog_datan3d.py,sha256=1jP4Kg86wfVX3Xal5MBG9T8IgQ5NqKedW9WsvIz7mtE,15857
7
- metradar/construct_aws_refvpr_mainprog_swan.py,sha256=uP1RqMX5191tRDh9bOKS_JM86Td1M66dr-RkpTepHy8,12175
8
4
  metradar/decode_fmt_pyart.py,sha256=cuiCX14E4BzQtTFJFfAGH4bJ1q7rXotilIxrLAqGI_I,7543
9
5
  metradar/decode_pup_rose.py,sha256=d5ajuJuM6X8kCiNGUBOrCeub6j2K9Y-Qgvjq4H-Qemc,82826
10
6
  metradar/draw_mosaic_new.py,sha256=1PyeNGa0Rpj_u-veXorer_bUeP7ogLMCpNbEcooKhus,16193
11
- metradar/draw_radar_aws_jilin_new.py,sha256=57RIy1u-1ENv_iJrSOxVLMI5Fcf4Erg5bWben4bDxpE,7904
12
7
  metradar/draw_radar_comp_func.py,sha256=Hc7TtZMLobW4VCPYPlYyq5MarVYBYDqgBhVJrYMgcHI,63969
13
8
  metradar/exceptions.py,sha256=C5jsADZix3E6Ah1sUPyBtgrGygy69lFc0QD5wO07a00,1300
14
9
  metradar/geo_transforms_pyart.py,sha256=7yOJOVLUaBnUQiesgvKZuESSNOx1uEYDilcRQAw5avM,21941
@@ -21,12 +16,10 @@ metradar/make_gif.py,sha256=rDNqhZXKAyQB_B2adU-ven07QgOTXwdY6eRFVsjTrdI,563
21
16
  metradar/make_mosaic_mp_archive.py,sha256=AXiTSSOL1ik0aLy-u4B_LjO4-sPVinhBqkTtPcMVlYI,19556
22
17
  metradar/mosaic_merge.py,sha256=eTTBJ5w2LchMBhjMHp1g97PGVcSzadoSKQwgtqjE4-M,1628
23
18
  metradar/mosaic_quickdraw.py,sha256=k0WI5hUKifCNSlbMrS8oJSBuM5XjWu5QDOkXoR50wFI,11910
24
- metradar/nowcast_by_pysteps.py,sha256=OcDY5Gb0pd1EM4pPD-bhIpoln3bH3aZ74J4DTCa4INk,7250
25
19
  metradar/oa_couhua.py,sha256=Gs85Lf1s5zuVdUQ3cuVUVF_h5KAQHOoNsQU4nvyUdHs,4414
26
20
  metradar/oa_dig_func.py,sha256=k3myqBg8jM901vrpKVZWgEL3RvZ06yQLJPV7O3l0Lng,34342
27
21
  metradar/parse_pal.py,sha256=dtF0hwXNoRFVHQygRs8lUePHPVRfoCvwvdAl1gRPjwg,5072
28
22
  metradar/pgmb_io.py,sha256=4D7beTSazhKTAzGwsQHaTxSn6PMqJpF4oOmMDIMuGio,5459
29
- metradar/prepare_for_radar_draw.py,sha256=59PRnUZ0olef272z8yYl8cC8H7lRQTRQc2VUhaTQXY8,6512
30
23
  metradar/read_new_mosaic.py,sha256=zE5Se0One0ev0mKn-_YOw3TfNf-ATPVGA8wVZg3_zbo,1205
31
24
  metradar/read_new_mosaic_func.py,sha256=dw_-b3H5n49G47PHbEtAxboECIgt28MLyZc0leLcAIs,7259
32
25
  metradar/retrieve_cmadaas.py,sha256=apwhisjHKfN6keahMgn73cVcA9jmEFGPOEmd6iX-xXc,137463
@@ -34,8 +27,7 @@ metradar/retrieve_micaps_server.py,sha256=cb-a_OKM1zCSw0tZ_Gk7RofE16RiRX6qq3oTUQ
34
27
  metradar/rose_structer.py,sha256=3EAZ18OXg0FXR4U1DNEvwU4gxP8mSRGkGUKjAW85IPs,25293
35
28
  metradar/trans_nc_pgmb.py,sha256=EfjaswKix4f8G-T1O6UKJ8lX9F_8z_IILucX_R2xdSk,1738
36
29
  metradar/trans_new_mosaic_nc.py,sha256=dZPr625hV7msFOgUVPwFgjTrTgQOEsIywMABzansPYA,9705
37
- metradar/trans_polor2grid_func.py,sha256=Ad6Ii_Ew3dwbRmN7RrRpDD-wU33xm7jbZAJbIVM3EsI,6864
38
- metradar-0.1.2.dist-info/METADATA,sha256=c7rQsd10vJB9ASXv894R6dGPh0xinouUHmTCwlnAEfE,579
39
- metradar-0.1.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
40
- metradar-0.1.2.dist-info/top_level.txt,sha256=vwxtTxux8rWm6wgfnwf0YWYrWjN16TZQCOy4h_OVwoE,9
41
- metradar-0.1.2.dist-info/RECORD,,
30
+ metradar-0.1.4.dist-info/METADATA,sha256=dKxSj6JuCz3XDkYKNmusu6sb4cGYDdb0JOmJmbdx0lA,1274
31
+ metradar-0.1.4.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
32
+ metradar-0.1.4.dist-info/top_level.txt,sha256=vwxtTxux8rWm6wgfnwf0YWYrWjN16TZQCOy4h_OVwoE,9
33
+ metradar-0.1.4.dist-info/RECORD,,
@@ -1,515 +0,0 @@
1
- #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
- '''
4
- @File : construct_aws_refvpr_mainprog.py
5
- @Time : 2023/08/19 20:58:59
6
- @Author : Wenjian Zhu
7
- @Version : 1.0
8
- @Email : kevin2075@163.com
9
- '''
10
-
11
- from retrieve_cmadaas import cmadaas_obs_by_time_range_and_id,cmadaas_get_radar_vol,cmadaas_sounding_by_time
12
- import pandas as pd
13
- import geo_transforms_pyart as geotrans
14
- import math
15
- import numpy as np
16
- import os
17
- import configparser
18
- from make_mosaic_mp_archive import MAKE_RADAR_MOSAIC
19
- from multiprocessing import freeze_support
20
- from datetime import datetime,timedelta
21
- import xarray as xr
22
- import numpy.ma as MA
23
- import matplotlib.pyplot as plt
24
- from parse_pal import parse_pro
25
- from matplotlib.ticker import (MultipleLocator)
26
- from matplotlib import font_manager
27
- import matplotlib
28
- from comm_func import geopotential_to_height
29
- matplotlib.use('agg')
30
- # 一键生成VPR数据和自动站数据,并绘制图形
31
- #数据来源:天擎
32
-
33
- class CONSTRUCT_VPR:
34
-
35
- # sub function for reading config file
36
- def ConfigFetchError(Exception):
37
- pass
38
-
39
- def _get_config_from_rcfile(self,rcfile):
40
- """
41
- Get configure information from config_dk_met_io.ini file.
42
- """
43
-
44
- rc = rcfile
45
- print(rc)
46
- if not os.path.exists(rc):
47
- print(rc + ' not exist')
48
- return None
49
- try:
50
- config = configparser.ConfigParser()
51
- config.read(rc,encoding='UTF-8')
52
- except IOError as e:
53
- raise self.ConfigFetchError(str(e))
54
- except Exception as e:
55
- raise self.ConfigFetchError(str(e))
56
-
57
- return config
58
-
59
- def __init__(self,inifilepath) -> None:
60
- pass
61
- config = self._get_config_from_rcfile(inifilepath)
62
- self.outpath = config['SETTINGS']['root_outpath']
63
- self.outpath_fmt = self.outpath + os.sep + config['SETTINGS']['radar_basedata_path']
64
- self.task_name = config['SETTINGS']['task_name']
65
-
66
- self.start_time = config['SETTINGS']['starttime']
67
- self.end_time = config['SETTINGS']['endtime']
68
- self.staid = config['SETTINGS']['aws_site']
69
- self.mosaic_range = int(config['SETTINGS']['mosaic_range'])
70
-
71
- self.pic_format = config['SETTINGS']['pic_format']
72
- self.pic_dpi = int(config['SETTINGS']['pic_dpi'])
73
- self.colorfile = config['SETTINGS']['colorfile']
74
- self.time_range = "[%s,%s]"%(self.start_time, self.end_time)
75
-
76
- # self.tlogp_time = '20230731000000'
77
- # 自动计算探空时间,用起始日期08时的探空
78
- self.tlogp_time = self.start_time[0:8] + '000000'
79
-
80
- self.outpath_tlogp = self.outpath + os.sep + 'tlogp'
81
- self.outpath_sta = self.outpath + os.sep + 'VPR'
82
- self.outpath_pic = self.outpath + os.sep + 'VPR'
83
- self.outpath_ref = self.outpath + os.sep + 'VPR'
84
- self.outname_sta= '%s.csv'%self.staid
85
- self.outname_ref = 'p3_vpr_%s_pyart.nc'%self.staid
86
- self.outpath_mosaic = self.outpath + os.sep + 'mosaic' + os.sep + self.task_name
87
-
88
- if not os.path.exists(self.outpath):
89
- os.makedirs(self.outpath)
90
- if not os.path.exists(self.outpath_fmt):
91
- os.makedirs(self.outpath_fmt)
92
- if not os.path.exists(self.outpath_tlogp):
93
- os.makedirs(self.outpath_tlogp)
94
- if not os.path.exists(self.outpath_sta):
95
- os.makedirs(self.outpath_sta)
96
- if not os.path.exists(self.outpath_pic):
97
- os.makedirs(self.outpath_pic)
98
- if not os.path.exists(self.outpath_ref):
99
- os.makedirs(self.outpath_ref)
100
- if not os.path.exists(self.outpath_mosaic):
101
- os.makedirs(self.outpath_mosaic)
102
-
103
- pass
104
-
105
- # 第一步,从天擎下载自动站数据
106
- def get_aws_data(self,):
107
- # 读取自动站雨量数据
108
- # A7606, A7607, A7055, A7617 重庆
109
- # # 54501 斋堂, A1067 丰台千灵山 A1254 大兴庞各庄
110
-
111
-
112
- elements='Station_Name,Station_Id_C,Station_Id_d,lat,lon,Datetime,PRE,PRE_1h'
113
-
114
- data_code = 'SURF_CHN_MUL_MIN'
115
-
116
- # 读取数据
117
- data = cmadaas_obs_by_time_range_and_id(time_range=self.time_range, data_code = data_code,elements=elements,sta_ids = self.staid)
118
- if data is None:
119
- print('required data is None, please check the site number!')
120
- return False
121
-
122
- self.sta_lat = data['lat'][0]
123
- self.sta_lon = data['lon'][0]
124
- self.sta_name = data['Station_Name'][0]
125
-
126
- # data.to_csv(outpath_sta + os.sep + outname_sta,index=False)
127
- data2 = data.set_index('Datetime')
128
- # data2['PRE_1h'][0]=0
129
-
130
-
131
- diff_rain =[]
132
- diff_rain.append(0)
133
-
134
-
135
- # PRE_1h表示当前小时的累计雨量
136
- # pre_5min表示当前5分钟的累计雨量
137
- # pre_1min表示当前1分钟的累计雨量
138
- # accsum表示从起始时刻到当前时刻的累计雨量
139
- # 时间均为UTC时间
140
-
141
- # diff()为求差,mode()为获取众数
142
- # steps 为数据的时间间隔,单位为分钟
143
- steps = int(data['Datetime'].diff().mode()[0].seconds/60)
144
- difrain_name = 'pre_%dmin'%steps
145
- for nn in np.arange(0,data2.shape[0]-1):
146
-
147
- if data2['PRE_1h'][nn+1] >= data2['PRE_1h'][nn]:
148
- diff_rain.append(round(data2['PRE_1h'][nn+1]-data2['PRE_1h'][nn],2))
149
- else:
150
- diff_rain.append(round(data2['PRE_1h'][nn+1],2))
151
- newpd = pd.DataFrame(diff_rain,columns=[difrain_name],index=data2.index)
152
- # 如果间隔是1分钟,那么还需要求出5分钟的雨量
153
- if steps == 1:
154
- newpd['pre_5min'] = newpd[difrain_name].rolling(5).sum()
155
- newpd['pre_5min'] = newpd['pre_5min'].round(2)
156
- else:
157
- pass
158
- newindex = [tt for tt in newpd.index if tt.minute%5==0]
159
- newpd['accsum'] = newpd[difrain_name].cumsum()
160
- newpd['accsum'] = newpd['accsum'].round(2)
161
- newpd['PRE_1h'] = data2['PRE_1h']
162
- newpd['PRE'] = data2['PRE']
163
- newpd['lat'] = data2['lat']
164
- newpd['lon'] = data2['lon']
165
- newpd['staname']=data2['Station_Name']
166
- newpd.to_csv(self.outpath_sta + os.sep + self.outname_sta,index=True,encoding='gbk')
167
- return True
168
-
169
- def get_tlogp_data(self,):
170
- # 第二步,从离自动站最近的探空站中获取探空数据,提取零度层高度和-20度层高度
171
- # 读取探空站信息,获取经纬度、站号等信息
172
- # tlogpinfo = pd.read_csv('../common/stationinfo_new/china_tlogp_stations_m3.txt',delimiter=r"\s+",skiprows=3,names=['stanum','lon','lat','alt','num2'])
173
-
174
- # tmpdata['stanum'].values[0] int
175
- # staid_tlogp = str(tmpdata['stanum'].values[0])
176
- tlogpdata = cmadaas_sounding_by_time(times=self.tlogp_time)
177
- allstas = np.unique(tlogpdata['Station_Id_C'])
178
- alllons=[]
179
- alllats=[]
180
- #获取所有站点的经纬度信息
181
- for ts in allstas:
182
- tmpd = tlogpdata[tlogpdata['Station_Id_C']==ts]
183
- curlat = tmpd['Lat'].values[0]
184
- curlon = tmpd['Lon'].values[0]
185
- alllons.append(curlon)
186
- alllats.append(curlat)
187
-
188
- x,y= geotrans.geographic_to_cartesian_aeqd(lon=alllons,lat=alllats,lon_0=self.sta_lon,lat_0=self.sta_lat)
189
- dis = [math.sqrt(pow(x[k],2) + pow(y[k],2))/1000 for k in range(len(x))]
190
- flag = np.array(dis) <= min(dis)+0.1
191
- tmpts = allstas[flag]
192
- tmpdata = tlogpdata[tlogpdata['Station_Id_C']==tmpts[0]]
193
- tmpdata = tmpdata.sort_values(by='PRS_HWC',ascending=False)
194
- tmpdata.dropna(subset=['PRS_HWC'],inplace=True)
195
- tmpdata.to_csv(self.outpath_tlogp + os.sep + 'tlogp_%s.csv'%tmpts[0],index=False)
196
- #查找离零度层和-20度层最近的高度
197
- flag = np.array(abs(tmpdata['TEM'])) <= abs(tmpdata['TEM']).min()+0.01
198
- z0 = tmpdata['GPH'][flag].values[0]
199
- flag = np.array(abs(tmpdata['TEM']+20)) <= abs(tmpdata['TEM']+20).min()+0.01
200
- z20 = tmpdata['GPH'][flag].values[0]
201
-
202
- self.z0 = geopotential_to_height(z0*9.80665)
203
- self.z20 = geopotential_to_height(z20*9.80665)
204
- return True
205
-
206
- def get_fmt_data(self,):
207
- # 第三步,从天擎读取雷达数据
208
- # 先检查是否已经存在拼图文件,而且拼图文件中的时间和范围能够覆盖当前自动站
209
- # 如果已经能满足要求,则不再下载雷达数据
210
- startt = datetime.strptime(self.start_time,'%Y%m%d%H%M%S')
211
- endt = datetime.strptime(self.end_time,'%Y%m%d%H%M%S')
212
- curt = startt
213
- allref=[]
214
- grd_height = None
215
- need_file_times=[]
216
- while curt <= endt:
217
-
218
- curname = 'mosaic_' + curt.strftime('%Y%m%d%H%M') + '.nc'
219
- if os.path.exists(self.outpath_mosaic + os.sep + curname):
220
- # print('file exist: %s'%(outpath_mosaic + os.sep + curname))
221
-
222
- ref = xr.open_dataset(self.outpath_mosaic + os.sep + curname)
223
-
224
- cent_lat = ref.origin_latitude.values[0]
225
- cent_lon = ref.origin_longitude.values[0]
226
- x,y= geotrans.geographic_to_cartesian_aeqd(lon=self.sta_lon,lat=self.sta_lat,lon_0=cent_lon,lat_0=cent_lat)
227
- grd_height = ref['z'].values
228
- reso_x = ref['x'][1]-ref['x'][0]
229
- reso_y = ref['y'][1]-ref['y'][0]
230
- xx = x[0]/reso_x
231
- yy = y[0]/reso_y
232
- xx = int(xx.round())
233
- yy = int(yy.round())
234
- radius = int((len(ref.x)-1)/2)
235
-
236
- if xx+radius >=0 and xx+radius < len(ref.x) and yy+radius >=0 and yy+radius < len(ref.y):
237
- pass
238
- else:
239
- # 表示当前拼图范围不能覆盖自动站,需要重新下载数据进行拼图
240
- need_file_times.append(curt)
241
- ref.close()
242
- else:
243
- need_file_times.append(curt)
244
- curt += timedelta(minutes=6)
245
-
246
-
247
-
248
- # 如果不能满足要求,则下载雷达数据
249
-
250
- # 根据自动站经纬度,自动判断应该下载哪些雷达站的数据
251
- # 读取雷达站点信息,获取经纬度、站号等信息
252
- valid_range = 200
253
- radinfo = pd.read_csv('metradar/radars.txt',sep='|',names=['radar_id','radar_name','gr2_name','radar_lat','radar_lon','radar_alt'],index_col=0)
254
-
255
- x,y = geotrans.geographic_to_cartesian_aeqd(radinfo['radar_lon'],radinfo['radar_lat'],self.sta_lon,self.sta_lat, R=6370997.0)
256
- # dis = math.sqrt(pow(x[0],2) + pow(y[0],2))
257
- dis = [math.sqrt(pow(x[k],2) + pow(y[k],2))/1000 for k in range(len(x))]
258
- flag = np.array(dis) <= valid_range
259
- # flag = np.where(dis<=valid_range)[0]
260
- tmpdata = radinfo.loc[flag]
261
- self.rdinfo = tmpdata.loc[:,['radar_name','radar_lat','radar_lon']]
262
-
263
-
264
- for site in self.rdinfo.index:
265
- print(site)
266
- # 从天擎下载该站号的雷达资料
267
- if len(need_file_times) == 0:
268
- # cmadaas_get_radar_vol(starttime=start_time,endtime=end_time,sta_ids=[site,],data_code= 'RADA_L2_FMT', outdir=outpath_fmt)
269
- pass
270
- else:
271
- tmp_starttime = min(need_file_times).strftime('%Y%m%d%H%M%S')
272
- tmp_endtime = max(need_file_times).strftime('%Y%m%d%H%M%S')
273
- cmadaas_get_radar_vol(starttime=tmp_starttime,endtime=tmp_endtime,sta_ids=[site,],data_code= 'RADA_L2_FMT', outdir=self.outpath_fmt)
274
-
275
- return True
276
- # 第四步,制作区域三维拼图
277
- def make_mosaic(self,):
278
- # 修改配置文件
279
- inifile_tmp = 'metradar/make_mosaic_mp_archive_vpr.ini'
280
- config = configparser.ConfigParser()
281
- config.read(inifile_tmp)
282
- config.set('ARCHIVE', 'input_path_archive', self.outpath_fmt) #
283
- config.set('ARCHIVE', 'output_path_archive', self.outpath_mosaic) #
284
- config.set('ARCHIVE', 'starttime', self.start_time[0:12]) #
285
- config.set('ARCHIVE', 'endtime', self.end_time[0:12]) #
286
- config.set('COMMON_SETTING', 'center_lon', '%.3f'%self.sta_lon) #
287
- config.set('COMMON_SETTING', 'center_lat', '%.3f'%self.sta_lat) #
288
- config.set('COMMON_SETTING', 'mosaic_range', '50') #
289
-
290
-
291
- str_site=''
292
- for site in self.rdinfo.index:
293
- str_site += site+','
294
- config.set('COMMON_SETTING', 'radars', str_site) #
295
- config.write(open(inifile_tmp, 'w')) # 将修改后的配置写入文件
296
-
297
- _make_mosaic = MAKE_RADAR_MOSAIC(inifile_tmp)
298
-
299
- if not _make_mosaic.berror:
300
- if _make_mosaic.run_mode == 'archive':
301
- _make_mosaic.do_archive()
302
- else:
303
- print('run mode is not archive!')
304
- return True
305
-
306
-
307
- # 第五步:从三维拼图数据中获取格点的时间序列
308
- def make_vpr(self,):
309
-
310
- data = pd.read_csv(self.outpath_sta+os.sep+self.outname_sta,index_col=0,encoding='gbk')
311
- sta_lat = data['lat'][0]
312
- sta_lon = data['lon'][0]
313
- sta_name = data['staname'][0]
314
- startt = datetime.strptime(self.start_time,'%Y%m%d%H%M%S')
315
- endt = datetime.strptime(self.end_time,'%Y%m%d%H%M%S')
316
- curt = startt
317
- allref=[]
318
- grd_height = None
319
- file_times=[]
320
- while curt <= endt:
321
-
322
- curname = 'mosaic_' + curt.strftime('%Y%m%d%H%M') + '.nc'
323
- if not os.path.exists(self.outpath_mosaic + os.sep + curname):
324
- print('file not exist: %s'%(self.outpath_mosaic + os.sep + curname))
325
- curt += timedelta(minutes=6)
326
- continue
327
-
328
- ref = xr.open_dataset(self.outpath_mosaic + os.sep + curname)
329
-
330
- cent_lat = ref.origin_latitude.values[0]
331
- cent_lon = ref.origin_longitude.values[0]
332
- x,y= geotrans.geographic_to_cartesian_aeqd(lon=sta_lon,lat=sta_lat,lon_0=cent_lon,lat_0=cent_lat)
333
- grd_height = ref['z'].values
334
- reso_x = ref['x'][1]-ref['x'][0]
335
- reso_y = ref['y'][1]-ref['y'][0]
336
- xx = x[0]/reso_x
337
- yy = y[0]/reso_y
338
- xx = int(xx.round())
339
- yy = int(yy.round())
340
- radius = int((len(ref.x)-1)/2)
341
- ref2 = ref.isel(x=xx+radius,y=yy+radius)['reflectivity'].values
342
- # 对ref2进行线性插值
343
- tmpdf = pd.DataFrame(ref2[0],columns=['ref_raw'])
344
- tmpdf['ref_new'] = tmpdf['ref_raw'].interpolate(method='slinear')
345
- ref2 = tmpdf['ref_new'].values
346
- allref.append(ref2)
347
- file_times.append(curt)
348
- curt += timedelta(minutes=6)
349
- ref.close()
350
- allref = np.array(allref)
351
- # allref = allref.reshape(allref.shape[0],allref.shape[2])
352
-
353
- alldata = MA.masked_array(allref, mask=allref==-9999)
354
- xrdata = xr.Dataset({
355
- 'dbz':(['z', 'time'], alldata.T, {'long name':'time-height dBZ'})},
356
- coords={'z':grd_height, 'time':file_times},
357
- attrs={'lat':sta_lat, 'lon':sta_lon})
358
-
359
- xrdata.to_netcdf(self.outpath_ref + os.sep + self.outname_ref)
360
- print('ref data success!')
361
- return True
362
-
363
- # 第六步,绘制图形
364
- def draw_pic(self,):
365
- oridf = pd.read_csv(self.outpath_sta+os.sep+self.outname_sta,encoding='gbk')#,index_col=0
366
-
367
- oridf['Datetime'] = pd.to_datetime(oridf['Datetime'], format="%Y-%m-%d %H:%M:%S")
368
- oridf = oridf.set_index('Datetime')
369
- newindex = [tt for tt in oridf.index if tt.minute%5==0]
370
- df = oridf.loc[newindex]
371
- # df.set_index('staname',inplace=True)
372
- df.reset_index(inplace=True)
373
-
374
- #将缺失的时间进行插值处理
375
- helper = pd.DataFrame({'Datetime': pd.date_range(start=df['Datetime'].min(), end=df['Datetime'].max(),freq='300s')})
376
- newdf = pd.merge(df, helper, on='Datetime', how='outer').sort_values('Datetime')
377
- newdf['accsum'] = newdf['accsum'].interpolate(method='linear')
378
-
379
- # ref_colorfile='gr2_colors/default_BR_PUP1.pal'
380
- # ref_colorfile = 'gr2_colors/BR_WDTB_Bright.pal'
381
- outdic= parse_pro(self.colorfile)
382
- cmap=outdic['cmap']
383
- norm=outdic['norm']
384
- units=outdic['units']
385
- # from pyart.graph import common
386
- # cmapname = 'pyart_NWSRef'
387
- # cmap = common.parse_cmap(cmapname, 'reflectivity')
388
-
389
- data = xr.open_dataset(self.outpath_ref + os.sep + self.outname_ref)
390
-
391
- data = data.rolling(z=2, time=2, min_periods=1, center=True).mean()
392
-
393
- font_path = 'resources/fonts/simsun.ttc'
394
- font_manager.fontManager.addfont(font_path)
395
- prop = font_manager.FontProperties(fname=font_path)
396
-
397
- plt.rcParams["font.size"] = 12
398
- plt.rcParams["font.sans-serif"] = prop.get_name()
399
- fig = plt.figure(figsize=(10,6))
400
- ax1 = fig.add_axes([0.1,0.18,0.8,0.3])#位置[左,下,右,上]
401
- ax3 = fig.add_axes([0.1,0.64,0.8,0.3])#位置[左,下,右,上]
402
- ax2 = ax3.twinx()
403
- ax1.minorticks_on()
404
-
405
-
406
- cb_ax = fig.add_axes([0.25, 0.08, 0.5, 0.03])
407
-
408
- grid_y,grid_x=np.meshgrid(np.arange(0,data.dbz.shape[1]),data.z.values,)
409
- pcm = ax1.pcolormesh(grid_y,grid_x,data.dbz,cmap=cmap,norm=norm)
410
- # pcm = ax1.pcolormesh(data.dbz,cmap=cmap,norm=norm)
411
-
412
-
413
- # flag = np.array(abs(data.z.values - z0)) <= abs(data.z.values - z0).min()+0.01
414
- # z0h = ax1.plot(np.arange(0,data.dbz.shape[1]),np.ones(data.dbz.shape[1])*int(np.where(flag)[0][0]),'y--',
415
- # linewidth=2,label='0度层高度')
416
- # flag = np.array(abs(data.z.values - z20)) <= abs(data.z.values - z20).min()+0.01
417
- # z20h=ax1.plot(np.arange(0,data.dbz.shape[1]),np.ones(data.dbz.shape[1])*int(np.where(flag)[0][0]),'r--',
418
- # linewidth=2,label='-20度层高度')
419
- z0h = ax1.plot(np.arange(0,data.dbz.shape[1]),np.ones(data.dbz.shape[1])*self.z0,'k--',linewidth=2,label='0度层高度')
420
- z20h=ax1.plot(np.arange(0,data.dbz.shape[1]),np.ones(data.dbz.shape[1])*self.z20,'r--',linewidth=2,label='-20度层高度')
421
-
422
- # leg = ax1.legend([z0h], ["零度层高度",], loc='upper right',title_fontproperties=prop)
423
- ax1.legend()
424
- ax1.tick_params(axis='x',which='minor',length=3,width=0.8,)
425
- ax1.tick_params(axis='x',which='major',length=5,width=1,)
426
- cb = plt.colorbar(mappable=pcm,cax=cb_ax,extend='both',ticks=np.arange(-10,85,5),orientation='horizontal')
427
- cb.set_label('反射率因子 dBZ',fontsize=12)
428
- ah1=ax2.plot(newdf['accsum'].values,'r',linewidth=2,label='累计雨量')
429
- ah2=ax3.bar(np.arange(0,newdf.shape[0]),newdf['pre_5min'],label='5分钟雨量')
430
- ax2.legend(loc='upper right')
431
- ax3.legend(loc='upper left')
432
- ax3.minorticks_on()
433
- ax3.tick_params(axis='x',which='minor',length=3,width=0.8,)
434
- ax3.tick_params(axis='x',which='major',length=5,width=1,)
435
- ax3.xaxis.set_minor_locator(MultipleLocator(1))
436
- ax1.set_xlim([0,data.dbz.shape[1]+1])
437
- ax2.set_xlim([0,newdf.shape[0]])
438
- ax1.grid('y')
439
- ax2.grid('y')
440
- # plt.xticks(fontsize=12)
441
- # plt.yticks(fontsize=12)
442
- # ax1.set_xlabel('Time(BJT, day hour:min)')
443
- ax1.set_ylabel('距离地面的高度(米)')
444
- ax1.set_title('单点回波强度时间-高度图(%.2f°N,%.2f°E)'%(data.lat,data.lon),fontsize=12)
445
- ax2.set_ylabel('累计雨量(毫米)',color='r')
446
- ax3.set_ylabel('5分钟雨量(毫米)',color=[59/255,117/255,175/255])
447
-
448
- tmpdate = pd.to_datetime(data.time)+ timedelta(hours=8)
449
- dates1 = [date.strftime('%H:%M') for date in tmpdate]
450
- dates1[0] = tmpdate.min().strftime('%H:%M \n%Y-%m-%d')
451
-
452
- datestr = dates1[::5]
453
- tmpd = tmpdate[::5]
454
- datestr[-1] = tmpd.max().strftime('%H:%M \n%Y-%m-%d')
455
-
456
- ax1.set_xticks(np.arange(0,data.time.shape[0],5))
457
- ax1.set_xticklabels(datestr)
458
- # ax1.set_yticks(np.arange(0,data.z.shape[0],5))
459
- # ax1.set_yticklabels(data.z[::5].values.astype('int'))
460
- # ax1.set_yticks(data.z[::5])
461
- # ax1.set_ylim([data.z.min(),data.z.max()])
462
- ax1.set_ylim([0,20000])
463
- ax1.set_yticks(np.arange(0,20000,2500))
464
-
465
- tmpdate = pd.to_datetime(newdf['Datetime'])+ timedelta(hours=8)
466
- dates2 = [date.strftime('%H:%M') for date in tmpdate]
467
- dates2[0] = tmpdate.min().strftime('%H:%M \n%Y-%m-%d')
468
- dates2[-1] = tmpdate.max().strftime('%H:%M \n%Y-%m-%d')
469
- ax2.set_xticks(np.arange(0,newdf.shape[0],6))
470
-
471
- ax2.set_xticklabels(dates2[::6])
472
- ax3.set_xlabel('时间(时:分,北京时)')
473
- ax2.set_title('5分钟雨量(柱)、自动站累积雨量(红实线), 站号:%s,%s(%.2f°N,%.2f°E)'%(self.staid,self.sta_name,self.sta_lat,self.sta_lon),fontsize=12)
474
- # plt.figtext(0.73,0.02,'国家气象中心-天气预报技术研发室制作',fontsize=10)
475
- plt.savefig(self.outpath_pic + os.sep + self.outname_ref.replace('.nc','.%s'%self.pic_format),dpi=self.pic_dpi)#,dpi=600
476
- print(self.outpath_pic + os.sep + self.outname_ref.replace('.nc','.%s'%self.pic_format) + ' saved!')
477
- # plt.show()
478
- plt.close()
479
- return True
480
-
481
- # 一键生成VPR数据和自动站数据,并绘制图形
482
- def do_all(self,):
483
-
484
- if not self.get_aws_data():
485
- return False
486
- if not self.get_tlogp_data():
487
- return False
488
- if not self.get_fmt_data():
489
- return False
490
- if not self.make_mosaic():
491
- return False
492
- if not self.make_vpr():
493
- return False
494
- if not self.draw_pic():
495
- return False
496
-
497
- if __name__ == "__main__":
498
-
499
-
500
- freeze_support()
501
-
502
- # sitelist=['G1174','G3522']
503
- # for st in sitelist:
504
- # _construct_vpr = CONSTRUCT_VPR(inifilepath='construct_aws_refvpr_mainprog_%s.ini'%st)
505
- # _construct_vpr.do_all()
506
-
507
- _construct_vpr = CONSTRUCT_VPR(inifilepath='metradar/construct_aws_refvpr_mainprog.ini')
508
- _construct_vpr.do_all()
509
-
510
-
511
-
512
-
513
-
514
-
515
-