metradar 0.1.6__py3-none-any.whl → 0.1.8.2__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 +4 -2
- metradar/config.py +53 -0
- metradar/core/__init__.py +9 -0
- metradar/{get_cross_section_from_pyart.py → core/get_cross_section.py} +5 -157
- metradar/{mosaic_merge.py → core/mosaic_merge.py} +3 -1
- metradar/{oa_dig_func.py → core/oa_dig_func.py} +83 -333
- metradar/graph/__init__.py +9 -0
- metradar/{mosaic_quickdraw.py → graph/draw_comp_mosaic.py} +71 -68
- metradar/{draw_mosaic_new.py → graph/draw_latlon_func.py} +177 -173
- metradar/graph/draw_radar_aws.py +212 -0
- metradar/{draw_radar_comp_func.py → graph/draw_radar_comp_func.py} +319 -248
- metradar/graph/parse_pal.py +157 -0
- metradar/io/__init__.py +9 -0
- metradar/{cnrad_level2.py → io/cnrad_level2.py} +45 -2
- metradar/{decode_fmt_pyart.py → io/decode_fmt_pyart.py} +20 -3
- metradar/{decode_pup_rose.py → io/decode_pup_rose.py} +241 -684
- metradar/{read_new_mosaic_func.py → io/read_new_mosaic_func.py} +30 -2
- metradar/io/read_swan.py +250 -0
- metradar/{rose_structer.py → io/rose_structer.py} +2 -0
- metradar/project/__init__.py +9 -0
- metradar/project/make_mosaic/__init__.py +9 -0
- metradar/project/make_mosaic/batch_draw_mosaic.py +32 -0
- metradar/{make_mosaic_mp_archive.py → project/make_mosaic/make_mosaic_func.py} +144 -175
- metradar/project/make_mosaic/make_mosaic_mp.ini +29 -0
- metradar/project/make_mosaic/make_mosaic_mp.py +70 -0
- metradar/project/make_vpr_aws/__init__.py +9 -0
- metradar/project/make_vpr_aws/construct_aws_refvpr_mainprog.ini +39 -0
- metradar/project/make_vpr_aws/construct_aws_refvpr_mainprog.py +565 -0
- metradar/project/make_vpr_aws/make_mosaic_20230731_daxing.ini +29 -0
- metradar/project/make_vpr_aws/make_mosaic_basefile.ini +29 -0
- metradar/project/nowcasting/__init__.py +9 -0
- metradar/project/nowcasting/nowcast_by_pysteps.py +214 -0
- metradar/{trans_nc_pgmb.py → project/nowcasting/trans_mosaic_pgmb.py} +19 -17
- metradar/project/qpe/Archive /346/250/241/345/274/217/350/257/264/346/230/216.txt" +2 -0
- metradar/project/qpe/__init__.py +9 -0
- metradar/project/qpe/archive_main_qpe_cfg.ini +91 -0
- metradar/project/qpe/do_s1.sh +6 -0
- metradar/project/qpe/do_s2.sh +6 -0
- metradar/project/qpe/do_s3.sh +6 -0
- metradar/project/qpe/do_s4.sh +6 -0
- metradar/project/qpe/do_s5.sh +6 -0
- metradar/project/qpe/exec_all.sh +11 -0
- metradar/project/qpe/get_rainrate_func.py +80 -0
- metradar/project/qpe/main_qpe_cfg.ini +85 -0
- metradar/project/qpe/s1_download_radar_region_cmadaas.py +123 -0
- metradar/project/qpe/s2_pre_process_single_radar.py +183 -0
- metradar/project/qpe/s3_trans_rainrate_to_qpe.py +499 -0
- metradar/project/qpe/s4_mosaic_qpe.py +523 -0
- metradar/project/qpe/s5_draw_qpe_mosaic.py +308 -0
- metradar/project/wind_retrieval/__init__.py +9 -0
- metradar/project/wind_retrieval/config_3dwind.ini +45 -0
- metradar/{main_pydda.py → project/wind_retrieval/main_pydda.py} +152 -149
- metradar/util/__init__.py +9 -0
- metradar/{comm_func.py → util/comm_func.py} +1 -41
- metradar/util/exceptions.py +50 -0
- metradar/util/geo_transforms_pyart.py +627 -0
- metradar/{get_tlogp_from_sharppy.py → util/get_tlogp_from_sharppy.py} +16 -5
- metradar/{parse_pal.py → util/parse_pal.py} +147 -147
- metradar/util/radar_common.py +16 -0
- metradar/{trans_new_mosaic_nc.py → util/trans_new_mosaic_nc.py} +1 -1
- metradar-0.1.8.2.dist-info/METADATA +90 -0
- metradar-0.1.8.2.dist-info/RECORD +69 -0
- {metradar-0.1.6.dist-info → metradar-0.1.8.2.dist-info}/WHEEL +1 -1
- metradar-0.1.8.2.dist-info/licenses/LICENSE +21 -0
- {metradar-0.1.6.dist-info → metradar-0.1.8.2.dist-info}/top_level.txt +0 -1
- cfg/config.py +0 -90
- metradar/grid.py +0 -281
- metradar/grid_data.py +0 -64
- metradar/oa_couhua.py +0 -166
- metradar/read_new_mosaic.py +0 -33
- metradar/retrieve_cmadaas.py +0 -3126
- metradar/retrieve_micaps_server.py +0 -2061
- metradar-0.1.6.dist-info/METADATA +0 -37
- metradar-0.1.6.dist-info/RECORD +0 -34
- /metradar/{pgmb_io.py → io/pgmb_io.py} +0 -0
- /metradar/{exceptions.py → project/make_vpr_aws/exceptions.py} +0 -0
- /metradar/{geo_transforms_pyart.py → project/make_vpr_aws/geo_transforms_pyart.py} +0 -0
- /metradar/{make_gif.py → util/make_gif.py} +0 -0
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
# _*_ coding: utf-8 _*_
|
|
2
|
+
|
|
3
|
+
'''
|
|
4
|
+
将单站qpe产品进行拼图处理
|
|
5
|
+
'''
|
|
6
|
+
# %%
|
|
7
|
+
import os
|
|
8
|
+
import numpy as np
|
|
9
|
+
import glob
|
|
10
|
+
from datetime import datetime,timedelta
|
|
11
|
+
from netCDF4 import Dataset
|
|
12
|
+
import xarray as xr
|
|
13
|
+
import pickle
|
|
14
|
+
import warnings
|
|
15
|
+
warnings.filterwarnings('ignore')
|
|
16
|
+
import configparser
|
|
17
|
+
#添加时间控制器
|
|
18
|
+
import time
|
|
19
|
+
import sched
|
|
20
|
+
import sys
|
|
21
|
+
from multiprocessing import Pool,cpu_count,freeze_support
|
|
22
|
+
import pandas as pd
|
|
23
|
+
schedule = sched.scheduler(time.time, time.sleep)
|
|
24
|
+
|
|
25
|
+
BDEBUG=False
|
|
26
|
+
|
|
27
|
+
# sub function for reading config file
|
|
28
|
+
def ConfigFetchError(BaseException):
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
def _get_config_from_rcfile(rcfile):
|
|
32
|
+
"""
|
|
33
|
+
Get configure information from config_dk_met_io.ini file.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
print(rcfile)
|
|
37
|
+
try:
|
|
38
|
+
config = configparser.ConfigParser()
|
|
39
|
+
config.read(rcfile,encoding='UTF-8')
|
|
40
|
+
except IOError as e:
|
|
41
|
+
raise ConfigFetchError(str(e))
|
|
42
|
+
except Exception as e:
|
|
43
|
+
raise ConfigFetchError(str(e))
|
|
44
|
+
|
|
45
|
+
return config
|
|
46
|
+
|
|
47
|
+
def get_datetime_from_filename1(filename):
|
|
48
|
+
timstr = filename[15:29]
|
|
49
|
+
fyear = int(timstr[0:4])
|
|
50
|
+
fmonth = int(timstr[4:6])
|
|
51
|
+
fday = int(timstr[6:8])
|
|
52
|
+
fhour = int(timstr[8:10])
|
|
53
|
+
fmin = int(timstr[10:12])
|
|
54
|
+
fsec = int(timstr[12:14])
|
|
55
|
+
ft = datetime(fyear,fmonth,fday,fhour,fmin,fsec).timestamp()
|
|
56
|
+
return ft
|
|
57
|
+
|
|
58
|
+
# Z9973_20240903_160311_01hr.nc
|
|
59
|
+
def get_datetime_from_filename2(filename):
|
|
60
|
+
timstr = filename[6:14] + filename[15:21]
|
|
61
|
+
fyear = int(timstr[0:4])
|
|
62
|
+
fmonth = int(timstr[4:6])
|
|
63
|
+
fday = int(timstr[6:8])
|
|
64
|
+
fhour = int(timstr[8:10])
|
|
65
|
+
fmin = int(timstr[10:12])
|
|
66
|
+
fsec = int(timstr[12:14])
|
|
67
|
+
ft = datetime(fyear,fmonth,fday,fhour,fmin,fsec).timestamp()
|
|
68
|
+
return ft
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def do_single(curt:datetime):
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# if BDEBUG:
|
|
76
|
+
# curt = datetime(2021,5,8,8,20,0)
|
|
77
|
+
# else:
|
|
78
|
+
# curt = datetime.utcnow()
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
if not os.path.exists(PATH_TMP):
|
|
82
|
+
os.makedirs(PATH_TMP)
|
|
83
|
+
|
|
84
|
+
for acc_hours in ACC_HOURS:
|
|
85
|
+
print('当前累积时段 = %d 小时'%acc_hours)
|
|
86
|
+
print(curt.strftime('当前执行时间为:%Y年%m月%d日%H时%M分(UTC)'))
|
|
87
|
+
# acc_hours = 3
|
|
88
|
+
# #降水产品格点设置
|
|
89
|
+
# START_LAT= 25
|
|
90
|
+
# END_LAT = 30
|
|
91
|
+
# START_LON= 109
|
|
92
|
+
# END_LON = 114
|
|
93
|
+
# MOSAIC_RESO = 0.01 #网格分辨率,经纬度,度
|
|
94
|
+
|
|
95
|
+
mosaic_lats = np.arange(START_LAT,END_LAT+MOSAIC_RESO/2,MOSAIC_RESO)
|
|
96
|
+
mosaic_lons = np.arange(START_LON,END_LON+MOSAIC_RESO/2,MOSAIC_RESO)
|
|
97
|
+
glons,glats = np.meshgrid(mosaic_lons,mosaic_lats)
|
|
98
|
+
|
|
99
|
+
GRID_XNUM = len(mosaic_lons)
|
|
100
|
+
GRID_YNUM = len(mosaic_lats)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# 获取所有单站数据的时间戳
|
|
104
|
+
allfiles = glob.glob(PATH_QPE + '/*/*')
|
|
105
|
+
dic_radfile = {rad:[] for rad in RADARS}
|
|
106
|
+
dic_radtime = {rad:[] for rad in RADARS}
|
|
107
|
+
|
|
108
|
+
for rd in RADARS:
|
|
109
|
+
curfilepath = PATH_QPE + os.sep + rd
|
|
110
|
+
print(curfilepath)
|
|
111
|
+
files = glob.glob(curfilepath + os.sep + '*%02dhr.nc'%acc_hours)
|
|
112
|
+
files = [file[-29::] for file in files]
|
|
113
|
+
files = sorted(files,reverse=True)
|
|
114
|
+
dic_radfile[rd] = files
|
|
115
|
+
for ff in files:
|
|
116
|
+
dic_radtime[rd].append(get_datetime_from_filename2(ff))
|
|
117
|
+
|
|
118
|
+
# 把过去30分钟的数据,每间隔6分钟的都处理一遍
|
|
119
|
+
cur_min = (curt.minute // MOSAIC_STEP)*MOSAIC_STEP
|
|
120
|
+
vlid_t = datetime(curt.year,curt.month,curt.day,curt.hour,cur_min,0)
|
|
121
|
+
checktimes = np.arange(vlid_t.timestamp(),vlid_t.timestamp()-REDO_MINS*60-1,-MOSAIC_STEP*60)
|
|
122
|
+
|
|
123
|
+
mosaic_path = PATH_QPE_MOSAIC + os.sep + '%02dhr'%acc_hours
|
|
124
|
+
if not os.path.exists(mosaic_path):
|
|
125
|
+
try:
|
|
126
|
+
os.makedirs(mosaic_path)
|
|
127
|
+
except:
|
|
128
|
+
print('创建目录失败:' + mosaic_path)
|
|
129
|
+
|
|
130
|
+
for mn in checktimes:
|
|
131
|
+
print(datetime.fromtimestamp(mn).strftime('正在执行 %Y年%m月%d日%H时%M分(UTC) 的拼图......'))
|
|
132
|
+
oldlist=[]
|
|
133
|
+
|
|
134
|
+
outname = 'QPE_MOSAIC_' + datetime.fromtimestamp(mn).strftime('%Y%m%d%H%M') + '_%02dhr.nc'%acc_hours
|
|
135
|
+
# 先判断该拼图是否已经存在,并且里面的文件列表无更新,如果是,就不重复处理,直接跳过
|
|
136
|
+
if os.path.exists(mosaic_path + os.sep + outname):
|
|
137
|
+
try:
|
|
138
|
+
tmplst = xr.open_dataset(mosaic_path + os.sep + outname)
|
|
139
|
+
oldlist = tmplst.basefile_info
|
|
140
|
+
except:
|
|
141
|
+
print('读取文件失败:' + mosaic_path + os.sep + outname)
|
|
142
|
+
|
|
143
|
+
validfnum=0
|
|
144
|
+
dic_validfile = {rad:[] for rad in RADARS}
|
|
145
|
+
for rd in RADARS:
|
|
146
|
+
if len(dic_radtime[rd]) == 0:
|
|
147
|
+
# 删除该键值
|
|
148
|
+
dic_validfile.pop(rd)
|
|
149
|
+
# dic_validfile[rd] = []
|
|
150
|
+
# print(rd + ' 无数据!')
|
|
151
|
+
continue
|
|
152
|
+
else:
|
|
153
|
+
tmpt = list(abs(np.array(dic_radtime[rd]) - mn))
|
|
154
|
+
#只查找时间差在正负3分钟以内的文件
|
|
155
|
+
if min(tmpt) <= 180:
|
|
156
|
+
dic_validfile[rd] = dic_radfile[rd][tmpt.index(min(tmpt))]
|
|
157
|
+
print('valid file: ' + dic_validfile[rd])
|
|
158
|
+
validfnum +=1
|
|
159
|
+
else:
|
|
160
|
+
pass
|
|
161
|
+
# print(dic_radfile[rd])
|
|
162
|
+
# print('%s 最短时间差为:%.1f秒,超过了三分钟的匹配时限'%(rd,min(tmpt)))
|
|
163
|
+
|
|
164
|
+
#查到当前时间的所有雷达的匹配数据后,进行拼图处理
|
|
165
|
+
if validfnum == 0:
|
|
166
|
+
print(datetime.fromtimestamp(mn).strftime('%Y年%m月%d日%H时%M分(UTC)') + ' 有效数据个数为0!')
|
|
167
|
+
continue
|
|
168
|
+
#
|
|
169
|
+
mosaic_grid=np.zeros([len(dic_validfile),GRID_YNUM,GRID_XNUM],dtype=float)
|
|
170
|
+
# 依次读取单站qpe产品,然后拼图
|
|
171
|
+
rflag=0
|
|
172
|
+
# dic_fileinfo = {key:[] for key in dic_validfile.keys()}
|
|
173
|
+
fileinfo_all = []
|
|
174
|
+
bbflag=False
|
|
175
|
+
for rd in dic_validfile.keys():
|
|
176
|
+
curfilepath = PATH_QPE + os.sep + rd
|
|
177
|
+
curfilename = dic_validfile[rd]
|
|
178
|
+
if len(curfilename) == 0:
|
|
179
|
+
continue
|
|
180
|
+
if not os.path.exists(curfilepath + os.sep + curfilename):
|
|
181
|
+
print(curfilepath + os.sep + curfilename + ' 文件不存在!')
|
|
182
|
+
continue
|
|
183
|
+
try:
|
|
184
|
+
# grid = pyart.io.read_grid(curfilepath + os.sep + curfilename)
|
|
185
|
+
grid = xr.open_dataset(curfilepath + os.sep + curfilename)
|
|
186
|
+
if not set(grid.basefile_info) <= set(oldlist):
|
|
187
|
+
bbflag = True
|
|
188
|
+
break
|
|
189
|
+
except:
|
|
190
|
+
print(curfilepath + os.sep + curfilename + ' 文件读取失败, continue!')
|
|
191
|
+
continue
|
|
192
|
+
if not bbflag:
|
|
193
|
+
print(outname + ' 拼图文件所用原始文件无更新,不重复处理!')
|
|
194
|
+
continue
|
|
195
|
+
|
|
196
|
+
used_sites=[]
|
|
197
|
+
used_lons=[]
|
|
198
|
+
used_lats=[]
|
|
199
|
+
used_hours=[]
|
|
200
|
+
|
|
201
|
+
for rd in dic_validfile.keys():
|
|
202
|
+
curfilepath = PATH_QPE + os.sep + rd
|
|
203
|
+
curfilename = dic_validfile[rd]
|
|
204
|
+
if len(curfilename) == 0:
|
|
205
|
+
continue
|
|
206
|
+
if not os.path.exists(curfilepath + os.sep + curfilename):
|
|
207
|
+
print(curfilepath + os.sep + curfilename + ' 文件不存在!')
|
|
208
|
+
continue
|
|
209
|
+
try:
|
|
210
|
+
# grid = pyart.io.read_grid(curfilepath + os.sep + curfilename)
|
|
211
|
+
grid = xr.open_dataset(curfilepath + os.sep + curfilename)
|
|
212
|
+
except:
|
|
213
|
+
print(curfilepath + os.sep + curfilename + ' 文件打开失败!')
|
|
214
|
+
continue
|
|
215
|
+
if set(grid.basefile_info) <= set(oldlist):
|
|
216
|
+
print('%s 站原始文件无变化: '%rd)
|
|
217
|
+
|
|
218
|
+
print('%s 站需制作新产品或原始文件有更新,处理:'%rd + curfilename + ' loaded!')
|
|
219
|
+
|
|
220
|
+
# check site location
|
|
221
|
+
# 先检查rd是否在ALL_RADARS的索引里面
|
|
222
|
+
if rd not in ALL_RADARS.index:
|
|
223
|
+
print('%s 站不在站号表文件radarsites_national.pkl中,请注意!'%rd)
|
|
224
|
+
|
|
225
|
+
if abs(grid.radlon - ALL_RADARS.loc[rd]['经度']) > 0.1 or abs(grid.radlat - ALL_RADARS.loc[rd]['纬度']) > 0.1:
|
|
226
|
+
print('%s 站的经度或纬度有异常,基数据中的记录的位置和站点表中记录的不一致,误差超过了0.1度,请注意,这里暂时以数据中记录的为准!'%rd)
|
|
227
|
+
print('基数据中记录的经度为%.3f, 纬度为%.3f'%(grid.radlon,grid.radlat))
|
|
228
|
+
print('站号表文件radarsites_national.pkl中记录的经度为%.3f, 纬度为%.3f'%(ALL_RADARS.loc[rd]['经度'],ALL_RADARS.loc[rd]['纬度']))
|
|
229
|
+
|
|
230
|
+
used_sites.append(rd)
|
|
231
|
+
used_lons.append(grid.radlon)
|
|
232
|
+
used_lats.append(grid.radlat)
|
|
233
|
+
|
|
234
|
+
for tmpff in grid.basefile_info:
|
|
235
|
+
fileinfo_all.append(tmpff)
|
|
236
|
+
used_hours.append(grid.used_hours)
|
|
237
|
+
#组合
|
|
238
|
+
mosaic_grid[rflag,:,:] = grid['qpe_mosaic'].values
|
|
239
|
+
|
|
240
|
+
rflag += 1
|
|
241
|
+
|
|
242
|
+
mosaic_grid = np.nanmean(mosaic_grid,axis=0)
|
|
243
|
+
|
|
244
|
+
# 输出到nc格式
|
|
245
|
+
try:
|
|
246
|
+
ncfile = Dataset(mosaic_path + os.sep + outname + '.lock', 'w', format='NETCDF4')
|
|
247
|
+
except:
|
|
248
|
+
try:
|
|
249
|
+
os.remove(mosaic_path + os.sep + outname+ '.lock')
|
|
250
|
+
try:
|
|
251
|
+
ncfile = Dataset(mosaic_path + os.sep + outname+ '.lock', 'w', format='NETCDF4')
|
|
252
|
+
except:
|
|
253
|
+
print(mosaic_path + os.sep + outname + '.lock' + ' 文件创建失败,删除成功,但无法再新建,跳过!')
|
|
254
|
+
continue
|
|
255
|
+
except:
|
|
256
|
+
print(mosaic_path + os.sep + outname + '.lock' + ' 文件创建失败,并且无法通过程序删除旧的同名文件,程序跳过!')
|
|
257
|
+
continue
|
|
258
|
+
|
|
259
|
+
hreso = MOSAIC_RESO
|
|
260
|
+
|
|
261
|
+
# global
|
|
262
|
+
ncfile.description = 'RADAR QPE MOSAIC '
|
|
263
|
+
# ncfile.author = 'Zhu WenJian, zhuwj@cma.gov.cn'
|
|
264
|
+
ncfile.reso = hreso
|
|
265
|
+
ncfile.start_lat = START_LAT
|
|
266
|
+
ncfile.end_lat = END_LAT
|
|
267
|
+
ncfile.start_lon = START_LON
|
|
268
|
+
ncfile.end_lon = END_LON
|
|
269
|
+
ncfile.product_time = datetime.fromtimestamp(mn).strftime('%Y%m%d%H%M')
|
|
270
|
+
ncfile.last_update = curt.strftime('%Y%m%d%H%M')
|
|
271
|
+
ncfile.basefile_info = list(fileinfo_all)
|
|
272
|
+
ncfile.used_sites = list(used_sites)
|
|
273
|
+
ncfile.used_lons = list(used_lons)
|
|
274
|
+
ncfile.used_lats = list(used_lats)
|
|
275
|
+
ncfile.used_hours = used_hours
|
|
276
|
+
|
|
277
|
+
unused_sites = [ss for ss in RADARS if not ss in used_sites]
|
|
278
|
+
ncfile.unused_sites = list(unused_sites)
|
|
279
|
+
unused_lons = [ALL_RADARS.loc[ll]['经度'] for ll in unused_sites]
|
|
280
|
+
unused_lats = [ALL_RADARS.loc[ll]['纬度'] for ll in unused_sites]
|
|
281
|
+
ncfile.unused_lons = list(unused_lons)
|
|
282
|
+
ncfile.unused_lats = list(unused_lats)
|
|
283
|
+
|
|
284
|
+
# dimensions
|
|
285
|
+
nlons = mosaic_lons
|
|
286
|
+
nlats = mosaic_lats
|
|
287
|
+
|
|
288
|
+
ncfile.createDimension('longitude', len(nlons))
|
|
289
|
+
ncfile.createDimension('latitude', len(nlats))
|
|
290
|
+
|
|
291
|
+
# variables
|
|
292
|
+
longitude = ncfile.createVariable('longitude', np.dtype('float32').char, ('longitude',))
|
|
293
|
+
longitude.units = 'degrees_east'
|
|
294
|
+
longitude.long_name = 'Longitude'
|
|
295
|
+
longitude.CoordinateAxisType = 'Lon'
|
|
296
|
+
|
|
297
|
+
latitude = ncfile.createVariable('latitude', np.dtype('float32').char, ('latitude',))
|
|
298
|
+
latitude.units = 'degrees_north'
|
|
299
|
+
latitude.long_name = 'Latitude'
|
|
300
|
+
latitude.CoordinateAxisType = 'Lat'
|
|
301
|
+
|
|
302
|
+
# H unsigned short
|
|
303
|
+
qpe_mosaic = ncfile.createVariable('qpe_mosaic', 'H', ('latitude', 'longitude'), zlib=True, least_significant_digit=1)
|
|
304
|
+
qpe_mosaic.unit_scale = 0.1
|
|
305
|
+
qpe_mosaic.long_name = "QPE MOSAIC"
|
|
306
|
+
qpe_mosaic.units='mm'
|
|
307
|
+
# data
|
|
308
|
+
qpe_mosaic[:,:] = mosaic_grid * 10
|
|
309
|
+
longitude[:] = nlons
|
|
310
|
+
latitude[:] = nlats
|
|
311
|
+
|
|
312
|
+
ncfile.close()
|
|
313
|
+
try:
|
|
314
|
+
os.rename(mosaic_path + os.sep + outname + '.lock',mosaic_path + os.sep + outname)
|
|
315
|
+
except:
|
|
316
|
+
print(mosaic_path + os.sep + outname + ' 重命名失败!')
|
|
317
|
+
|
|
318
|
+
print(mosaic_path + os.sep + outname + ' done!')
|
|
319
|
+
except :
|
|
320
|
+
print(mosaic_path + os.sep + outname + ' + do_single 失败,跳过!')
|
|
321
|
+
|
|
322
|
+
def get_time_range_from_filelist():
|
|
323
|
+
#从数据目录里面获取时间范围,用于后续处理
|
|
324
|
+
trange ={}
|
|
325
|
+
# 对雷达进行遍历
|
|
326
|
+
for rd in RADARS:
|
|
327
|
+
curpath = PATH_QPE + os.sep + rd
|
|
328
|
+
if not os.path.exists(curpath):
|
|
329
|
+
continue
|
|
330
|
+
ff = os.listdir(curpath)
|
|
331
|
+
ft=[]
|
|
332
|
+
for f in ff:
|
|
333
|
+
if f[-3:] == 'nc':
|
|
334
|
+
continue
|
|
335
|
+
#从文件名中获取时间
|
|
336
|
+
t = get_datetime_from_filename2(f)
|
|
337
|
+
ft.append(t)
|
|
338
|
+
#对ft进行排序
|
|
339
|
+
ft.sort()
|
|
340
|
+
trange[rd] = [ft[0],ft[-1]]
|
|
341
|
+
#计算时间范围
|
|
342
|
+
trange[rd].append(int((trange[rd][1]-trange[rd][0])/3600))
|
|
343
|
+
print('Radar %s has %d files, start time is %s, end time is %s, time range is %d hours'%(rd,len(ft),datetime.fromtimestamp(trange[rd][0]).strftime('%Y%m%d%H%M'),datetime.fromtimestamp(trange[rd][1]).strftime('%Y%m%d%H%M'),trange[rd][2]))
|
|
344
|
+
|
|
345
|
+
#对所有雷达的时间范围进行合并,并将tmin和tmax存为datetime类型
|
|
346
|
+
|
|
347
|
+
tmin = trange[RADARS[0]][0]
|
|
348
|
+
tmax = trange[RADARS[0]][1]
|
|
349
|
+
for rd in RADARS:
|
|
350
|
+
if trange[rd][0] < tmin:
|
|
351
|
+
tmin = trange[rd][0]
|
|
352
|
+
if trange[rd][1] > tmax:
|
|
353
|
+
tmax = trange[rd][1]
|
|
354
|
+
# 把tmin往前取整10分钟,把tmax往后取整10分钟
|
|
355
|
+
tmin = tmin - tmin%600
|
|
356
|
+
tmax = tmax + 600 - tmax%600
|
|
357
|
+
# print
|
|
358
|
+
print('All radar has %d files, start time is %s, end time is %s, time range is %d hours'%(len(ft),datetime.fromtimestamp(tmin).strftime('%Y%m%d%H%M'),datetime.fromtimestamp(tmax).strftime('%Y%m%d%H%M'),int((tmax-tmin)/3600)))
|
|
359
|
+
|
|
360
|
+
return tmin,tmax
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def do_mosaic_qpe(tstep=10):
|
|
364
|
+
# ACC_HOURS = [3],
|
|
365
|
+
# START_LAT= 25,
|
|
366
|
+
# END_LAT = 30,
|
|
367
|
+
# START_LON= 109,
|
|
368
|
+
# END_LON = 114,
|
|
369
|
+
# MOSAIC_RESO = 0.01,
|
|
370
|
+
# RADARS = ['Z9734','Z9731','Z9739','Z9746'],
|
|
371
|
+
# PATH_QPE = 'out_qpe',
|
|
372
|
+
# PATH_QPE_MOSAIC='qpe_mosaic',
|
|
373
|
+
# PATH_TMP='tmp',
|
|
374
|
+
# REDO_MINS=20,
|
|
375
|
+
|
|
376
|
+
#如果是历史模式
|
|
377
|
+
if RUNMODE == 1: # 对小时进行累计
|
|
378
|
+
# timestamp类型
|
|
379
|
+
startt,endt = get_time_range_from_filelist()
|
|
380
|
+
# 按拼图间隔,从startt,处理到endt,具体采用do_single函数
|
|
381
|
+
# 每个时刻单独分配一个进程,采用多进程处理
|
|
382
|
+
_pools = Pool(CPU_MAX)
|
|
383
|
+
t = startt
|
|
384
|
+
allt=[]
|
|
385
|
+
while t <= endt:
|
|
386
|
+
#将t转换为datetime类型
|
|
387
|
+
allt.append(datetime.fromtimestamp(t))
|
|
388
|
+
t += MOSAIC_STEP*60
|
|
389
|
+
|
|
390
|
+
_pools.map(do_single,allt)
|
|
391
|
+
_pools.close()
|
|
392
|
+
_pools.join()
|
|
393
|
+
elif RUNMODE == 2: # 对分钟进行累计
|
|
394
|
+
# timestamp类型
|
|
395
|
+
startt,endt = get_time_range_from_filelist()
|
|
396
|
+
# 按拼图间隔,从startt,处理到endt,具体采用do_single函数
|
|
397
|
+
# 每个时刻单独分配一个进程,采用多进程处理
|
|
398
|
+
_pools = Pool(CPU_MAX)
|
|
399
|
+
t = startt
|
|
400
|
+
allt=[]
|
|
401
|
+
while t <= endt:
|
|
402
|
+
#将t转换为datetime类型
|
|
403
|
+
allt.append(datetime.fromtimestamp(t))
|
|
404
|
+
t += MOSAIC_STEP*60
|
|
405
|
+
|
|
406
|
+
_pools.map(do_single,allt)
|
|
407
|
+
_pools.close()
|
|
408
|
+
_pools.join()
|
|
409
|
+
else:
|
|
410
|
+
#将curt设置为当前UTC时间
|
|
411
|
+
curt = datetime.utcnow()
|
|
412
|
+
|
|
413
|
+
do_single(curt)
|
|
414
|
+
|
|
415
|
+
if not BDEBUG:
|
|
416
|
+
print('Waiting for new data......')
|
|
417
|
+
schedule.enter(tstep, 0, do_mosaic_qpe, (tstep,))
|
|
418
|
+
|
|
419
|
+
def _delete_old_data(tstep):
|
|
420
|
+
|
|
421
|
+
print('delete expired data ...')
|
|
422
|
+
curtime = datetime.now()
|
|
423
|
+
pretime = curtime + timedelta(hours=-1*int(data_save_hours))
|
|
424
|
+
|
|
425
|
+
#查询过期数据
|
|
426
|
+
# curpath = PATH_TMP
|
|
427
|
+
# if not os.path.exists(curpath):
|
|
428
|
+
# return False
|
|
429
|
+
# ff = os.listdir(curpath)
|
|
430
|
+
# for f in ff:
|
|
431
|
+
# t = os.path.getctime(curpath + os.sep + f)
|
|
432
|
+
# if t < pretime.timestamp():
|
|
433
|
+
# os.remove(curpath + os.sep + f)
|
|
434
|
+
# print(['Delete file:' + curpath + os.sep + f])
|
|
435
|
+
|
|
436
|
+
for acc_hours in ACC_HOURS:
|
|
437
|
+
curpath = PATH_QPE_MOSAIC + os.sep + '%02dhr'%acc_hours
|
|
438
|
+
if not os.path.exists(curpath):
|
|
439
|
+
return False
|
|
440
|
+
ff = os.listdir(curpath)
|
|
441
|
+
for f in ff:
|
|
442
|
+
t = os.path.getctime(curpath + os.sep + f)
|
|
443
|
+
if t < pretime.timestamp():
|
|
444
|
+
os.remove(curpath + os.sep + f)
|
|
445
|
+
print(['Delete file:' + curpath + os.sep + f])
|
|
446
|
+
|
|
447
|
+
schedule.enter(tstep, 0, _delete_old_data, (tstep,))
|
|
448
|
+
|
|
449
|
+
if __name__ == "__main__":
|
|
450
|
+
|
|
451
|
+
print('Usage: python s4_mosaic_qpe.py inifile')
|
|
452
|
+
# 所有参数(包含脚本名)
|
|
453
|
+
all_args = sys.argv
|
|
454
|
+
# 实际参数(排除脚本名)
|
|
455
|
+
inifile = sys.argv[1:]
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
#如果未指定配置文件,则选用默认的配置
|
|
459
|
+
if len(inifile) ==0:
|
|
460
|
+
inifile = '/home/wjzhu/OneDrive/PythonCode/MyWork/metradar/metradar/project/qpe/main_qpe_cfg.ini'
|
|
461
|
+
# inifile = 'archive_main_qpe_cfg.ini'
|
|
462
|
+
else:
|
|
463
|
+
inifile = inifile[0]
|
|
464
|
+
|
|
465
|
+
config = _get_config_from_rcfile(inifile)
|
|
466
|
+
RUNMODE = int(config['COMMON']['RUN_MODE'])#X方向格点数
|
|
467
|
+
if RUNMODE == 0:
|
|
468
|
+
BDEBUG = False
|
|
469
|
+
else:
|
|
470
|
+
BDEBUG = True
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
ROOT_PATH = config['PATH_SETTING']['ROOT_PATH']
|
|
474
|
+
BASEDATA_PATH = ROOT_PATH + os.sep + config['PATH_SETTING']['BASEDATA_PATH']
|
|
475
|
+
RADAR_SITES_FILE = config['PATH_SETTING']['RADAR_SITES_FILE']
|
|
476
|
+
RADARS = config['RADAR_SITES']['RADARS'].split(',')
|
|
477
|
+
PATH_QPE = ROOT_PATH + os.sep + config['PATH_SETTING']['PATH_QPE']
|
|
478
|
+
PATH_QPE_MOSAIC = ROOT_PATH + os.sep + config['PATH_SETTING']['PATH_QPE_MOSAIC']
|
|
479
|
+
PATH_TMP = ROOT_PATH + os.sep + config['PATH_SETTING']['PATH_TMP']
|
|
480
|
+
data_save_hours = config['DATA_SAVE_SETTING']['DATA_SAVE_HOURS']
|
|
481
|
+
ACC_HOURS = [int(mm) for mm in config['PARAMS']['acc_hours'].split(',')]
|
|
482
|
+
if not os.path.exists(PATH_QPE_MOSAIC):
|
|
483
|
+
try:
|
|
484
|
+
os.makedirs(PATH_QPE_MOSAIC)
|
|
485
|
+
except:
|
|
486
|
+
print('创建目录失败:' + PATH_QPE_MOSAIC)
|
|
487
|
+
|
|
488
|
+
CPU_MAX = int(cpu_count() * float(config['PARAMS']['CPU_RATE']))
|
|
489
|
+
#降水产品格点设置
|
|
490
|
+
MOSAIC_RESO = float(config['PARAMS']['MOSAIC_RESO']) #网格分辨率,度
|
|
491
|
+
START_LAT = float(config['PARAMS']['SOUTH_LAT']) #南纬
|
|
492
|
+
END_LAT = float(config['PARAMS']['NORTH_LAT']) #北纬
|
|
493
|
+
START_LON = float(config['PARAMS']['WEST_LON']) #西经
|
|
494
|
+
END_LON = float(config['PARAMS']['EAST_LON']) #东经
|
|
495
|
+
|
|
496
|
+
REDO_MINS = int(config['PARAMS']['REDO_MINS'])
|
|
497
|
+
MOSAIC_STEP = int(config['PARAMS']['MOSAIC_STEP'])
|
|
498
|
+
|
|
499
|
+
if not os.path.exists(RADAR_SITES_FILE):
|
|
500
|
+
print(RADAR_SITES_FILE + ' 文件不存在,程序退出!')
|
|
501
|
+
exit(-1)
|
|
502
|
+
ALL_RADARS = pd.read_csv(RADAR_SITES_FILE,header=0,index_col=0)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
with open('current_pid_s4_%d.txt'%RUNMODE,'wt') as f:
|
|
506
|
+
f.write('current pid is: %s'%str(os.getpid()) + ' ,' + datetime.now().strftime('%Y-%m-%dT%H:%M:%S'))
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
tstep=10
|
|
510
|
+
|
|
511
|
+
if not BDEBUG:
|
|
512
|
+
# 增加数据处理任务
|
|
513
|
+
schedule.enter(0, 0, do_mosaic_qpe, (tstep,))
|
|
514
|
+
|
|
515
|
+
# 增加数据管理任务,定时删除旧文件
|
|
516
|
+
schedule.enter(0, 0, _delete_old_data, (60,))
|
|
517
|
+
|
|
518
|
+
# 增加程序自动重启任务,以解决可能存在的bug
|
|
519
|
+
schedule.run()
|
|
520
|
+
else:
|
|
521
|
+
do_mosaic_qpe(tstep)
|
|
522
|
+
|
|
523
|
+
# %%
|