metradar 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- metradar/__init__.py +7 -0
- metradar/cnrad_level2.py +1326 -0
- metradar/comm_func.py +135 -0
- metradar/construct_aws_refvpr_mainprog.py +515 -0
- metradar/construct_aws_refvpr_mainprog_cams.py +310 -0
- metradar/construct_aws_refvpr_mainprog_datan3d.py +386 -0
- metradar/construct_aws_refvpr_mainprog_swan.py +306 -0
- metradar/decode_fmt_pyart.py +200 -0
- metradar/decode_pup_rose.py +1993 -0
- metradar/draw_mosaic_new.py +421 -0
- metradar/draw_radar_aws_jilin_new.py +206 -0
- metradar/draw_radar_comp_func.py +1379 -0
- metradar/exceptions.py +50 -0
- metradar/geo_transforms_pyart.py +627 -0
- metradar/get_cross_section_from_pyart.py +354 -0
- metradar/get_tlogp_from_sharppy.py +93 -0
- metradar/grid.py +281 -0
- metradar/grid_data.py +64 -0
- metradar/main_pydda.py +653 -0
- metradar/make_gif.py +24 -0
- metradar/make_mosaic_mp_archive.py +538 -0
- metradar/mosaic_merge.py +64 -0
- metradar/mosaic_quickdraw.py +338 -0
- metradar/nowcast_by_pysteps.py +219 -0
- metradar/oa_couhua.py +166 -0
- metradar/oa_dig_func.py +955 -0
- metradar/parse_pal.py +148 -0
- metradar/pgmb_io.py +169 -0
- metradar/prepare_for_radar_draw.py +197 -0
- metradar/read_new_mosaic.py +33 -0
- metradar/read_new_mosaic_func.py +231 -0
- metradar/retrieve_cmadaas.py +3126 -0
- metradar/retrieve_micaps_server.py +2061 -0
- metradar/rose_structer.py +807 -0
- metradar/trans_nc_pgmb.py +62 -0
- metradar/trans_new_mosaic_nc.py +309 -0
- metradar/trans_polor2grid_func.py +203 -0
- metradar-0.1.0.dist-info/METADATA +12 -0
- metradar-0.1.0.dist-info/RECORD +41 -0
- metradar-0.1.0.dist-info/WHEEL +5 -0
- metradar-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'''
|
|
2
|
+
测试将雷达拼图输出成pgmb格式
|
|
3
|
+
|
|
4
|
+
'''
|
|
5
|
+
|
|
6
|
+
# %%
|
|
7
|
+
from pgmb_io import pgmb_write
|
|
8
|
+
import os
|
|
9
|
+
from read_new_mosaic import decode_mosaic
|
|
10
|
+
import xarray as xr
|
|
11
|
+
import numpy as np
|
|
12
|
+
import gzip
|
|
13
|
+
|
|
14
|
+
def zip_file(path, new_path):
|
|
15
|
+
with open(new_path, 'wb') as wf:
|
|
16
|
+
with open(path, 'rb') as rf:
|
|
17
|
+
data = rf.read()
|
|
18
|
+
# 压缩数据
|
|
19
|
+
data_comp = gzip.compress(data,compresslevel=5)
|
|
20
|
+
wf.write(data_comp)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
filepath = '/Users/wenjianzhu/Downloads/CMADAAS/rdmosaic_bin/202307/'
|
|
24
|
+
for filename in os.listdir(filepath):
|
|
25
|
+
if not filename.endswith('.nc'):
|
|
26
|
+
continue
|
|
27
|
+
# filename = 'ACHN.CREF000.20230421.180009.nc'
|
|
28
|
+
obstimestr = filename.split('.')[2] + filename.split('.')[3][0:4]
|
|
29
|
+
outname = filename.split('.')[2] + filename.split('.')[3][0:4] + '_fmi.radar.composite.lowest_FIN_SUOMI1.pgm'
|
|
30
|
+
outpath = '/Users/wenjianzhu/pysteps_data/radar/fmi/pgm/%s'%filename.split('.')[2]
|
|
31
|
+
if not os.path.exists(outpath):
|
|
32
|
+
os.makedirs(outpath)
|
|
33
|
+
|
|
34
|
+
file_name = outpath + os.sep + outname
|
|
35
|
+
|
|
36
|
+
org_data = xr.open_dataset(filepath+os.sep+filename)
|
|
37
|
+
data = org_data.sel(lat=slice(33, 37), lon=slice(109, 117))
|
|
38
|
+
|
|
39
|
+
width = data.cref.shape[1]
|
|
40
|
+
height = data.cref.shape[0]
|
|
41
|
+
maxval = 255
|
|
42
|
+
gray = data.cref*2+66
|
|
43
|
+
|
|
44
|
+
aa = np.isnan(gray.data)
|
|
45
|
+
gray.data[aa]=255
|
|
46
|
+
cref = np.flipud(gray.data.astype(np.uint8))
|
|
47
|
+
params={}
|
|
48
|
+
params['obstimestr'] = obstimestr
|
|
49
|
+
params['left_lon'] = 109
|
|
50
|
+
params['right_lon'] = 117
|
|
51
|
+
params['bottom_lat'] = 33
|
|
52
|
+
params['upper_lat'] = 37
|
|
53
|
+
|
|
54
|
+
pgmb_write ( file_name, params, width, height, maxval, cref )
|
|
55
|
+
|
|
56
|
+
# gzip file
|
|
57
|
+
|
|
58
|
+
# zip_file(file_name, file_name + '.gz')
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
print('write pgmb file %s successfully!'%(file_name))
|
|
62
|
+
# break
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
'''
|
|
2
|
+
读取新的雷达拼图数据
|
|
3
|
+
朱文剑
|
|
4
|
+
20210830
|
|
5
|
+
|
|
6
|
+
数据格式说明
|
|
7
|
+
|
|
8
|
+
//
|
|
9
|
+
/////////////////////////////////////////////////////////////////////
|
|
10
|
+
// 组网定量估测降水系统拼图产品文件规则
|
|
11
|
+
// 1. 文件里命名为:
|
|
12
|
+
// ACHN_XXX_20121012_090000_nn.bin
|
|
13
|
+
// 2. 文件格式:文件头 + 数据块
|
|
14
|
+
// 3. 数据从西北,往东南写
|
|
15
|
+
//***************************************
|
|
16
|
+
typedef struct tagMQPE_MosiacProductHeaderStructure
|
|
17
|
+
{
|
|
18
|
+
// 文件卷标,12字节(0-11),
|
|
19
|
+
char label[4]; //0-3 文件固定标识:MOC
|
|
20
|
+
char Version[4]; //4-7 文件格式版本代码,如: 1.0,1.1,etc
|
|
21
|
+
int FileBytes; //8-11 包含头信息在内的文件字节数,不超过2M
|
|
22
|
+
|
|
23
|
+
//产品描述, 84字节(12-95)
|
|
24
|
+
short MosaicID; //12-13 拼图产品编号
|
|
25
|
+
short coordinate; //14-15 坐标类型: 2=笛卡儿坐标,3=等经纬网格坐标
|
|
26
|
+
char varname[8]; //16-23 产品代码,如: ET,VIL,CR,CAP,OHP,OHPC
|
|
27
|
+
char description[64];//24-87 产品描述,如Composite Reflectivity mosaic
|
|
28
|
+
int BlockPos; //88-91 产品数据起始位置(字节顺序)
|
|
29
|
+
int BlockLen; //92-95 产品数据字节数
|
|
30
|
+
|
|
31
|
+
//数据时间, 28字节(96-123)
|
|
32
|
+
int TimeZone; //96-99 数据时钟,0=世界时,28800=北京时
|
|
33
|
+
short yr; //100-101 观测时间中的年份
|
|
34
|
+
short mon; //102-103 观测时间中的月份(1-12)
|
|
35
|
+
short day; //104-105 观测时间中的日期(1-31)
|
|
36
|
+
short hr; //106-107 观测时间中的小时(00-23)
|
|
37
|
+
short min; //108-109 观测时间中的分(00-59)
|
|
38
|
+
short sec; //110-111 观测时间中的秒(00-59)
|
|
39
|
+
int ObsSeconds; //112-115 观测时间的seconds
|
|
40
|
+
unsigned short ObsDates; //116-117 观测时间中的Julian dates
|
|
41
|
+
unsigned short GenDates; //118-119 产品处理时间的天数
|
|
42
|
+
int GenSeconds; //120-123 产品处理时间的描述
|
|
43
|
+
|
|
44
|
+
//数据区信息, 48字节(124-171)
|
|
45
|
+
int edge_s; //124-127 数据区的南边界,单位:1/1000度,放大1千倍
|
|
46
|
+
int edge_w; //128-131 数据区的西边界,单位:1/1000度,放大1千倍
|
|
47
|
+
int edge_n; //132-135 数据区的北边界,单位:1/1000度,放大1千倍
|
|
48
|
+
int edge_e; //136-139 数据区的东边界,单位:1/1000度,放大1千倍
|
|
49
|
+
int cx; //140-143 数据区中心坐标,单位:1/1000度,放大1千倍
|
|
50
|
+
int cy; //144-147 数据区中心坐标,单位:1/1000度,放大1千倍
|
|
51
|
+
int nX; //148-151 格点坐标为列数,
|
|
52
|
+
int nY; //152-155 格点坐标为行数,
|
|
53
|
+
int dx; //156-159 格点坐标为列分辨率,单位:1/10000度,放大1万倍
|
|
54
|
+
int dy; //160-163 格点坐标为行分辨率,单位:1/10000度,放大1万倍
|
|
55
|
+
short height; //164-165 雷达高度
|
|
56
|
+
short Compress; //166-167 数据压缩标识, 0=无,1=bz2,2=zip,3=lzw
|
|
57
|
+
int num_of_radars; //168-171有多少个雷达进行了拼图
|
|
58
|
+
|
|
59
|
+
int UnZipBytes; //数据段压缩前的字节数, //172-175
|
|
60
|
+
short scale; //176-177
|
|
61
|
+
short unUsed; //178-179
|
|
62
|
+
char RgnID[8]; //180-187
|
|
63
|
+
char units[8]; //180-187
|
|
64
|
+
char reserved[60];
|
|
65
|
+
}MOSAIC_PRODUCTHEADER;
|
|
66
|
+
|
|
67
|
+
-32768表示空白
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
'''
|
|
71
|
+
|
|
72
|
+
# %%
|
|
73
|
+
CODE1 = 'B'
|
|
74
|
+
CODE2 = 'H'
|
|
75
|
+
INT1 = 'B'
|
|
76
|
+
INT2 = 'H'
|
|
77
|
+
INT4 = 'I'
|
|
78
|
+
REAL4 = 'f'
|
|
79
|
+
REAL8 = 'd'
|
|
80
|
+
SINT1 = 'b'
|
|
81
|
+
SINT2 = 'h'
|
|
82
|
+
SINT4 = 'i'
|
|
83
|
+
|
|
84
|
+
MOSAIC_HEADER = (
|
|
85
|
+
('label', '4s'),
|
|
86
|
+
('Version', '4s'),
|
|
87
|
+
('FileBytes', INT4),
|
|
88
|
+
('MosaicID', INT2),
|
|
89
|
+
('coordinate', INT2),
|
|
90
|
+
('varname', '8s'),
|
|
91
|
+
('description', '64s'),
|
|
92
|
+
('BlockPos', INT4),
|
|
93
|
+
('BlockLen', INT4),
|
|
94
|
+
('TimeZone', INT4),
|
|
95
|
+
('year', INT2),
|
|
96
|
+
('month', INT2),
|
|
97
|
+
('day', INT2),
|
|
98
|
+
('hour', INT2),
|
|
99
|
+
('min', INT2),
|
|
100
|
+
('sec', INT2),
|
|
101
|
+
('ObsSeconds', INT4),
|
|
102
|
+
('ObsDates', INT2),
|
|
103
|
+
('GenDates', INT2),
|
|
104
|
+
('GenSeconds', INT4),
|
|
105
|
+
('edge_s', INT4),
|
|
106
|
+
('edge_w', INT4),
|
|
107
|
+
('edge_n', INT4),
|
|
108
|
+
('edge_e', INT4),
|
|
109
|
+
('cx', INT4),
|
|
110
|
+
('cy', INT4),
|
|
111
|
+
('nX', INT4),
|
|
112
|
+
('nY', INT4),
|
|
113
|
+
('dx', INT4),
|
|
114
|
+
('dy', INT4),
|
|
115
|
+
('height', INT2),
|
|
116
|
+
('Compress', INT2),
|
|
117
|
+
('num_of_radars', INT4),
|
|
118
|
+
('UnZipBytes', INT4),
|
|
119
|
+
('scale', INT2),
|
|
120
|
+
('unUsed', INT2),
|
|
121
|
+
('RgnID', '8s'),
|
|
122
|
+
('units', '8s'),
|
|
123
|
+
('reserved', '60s'),
|
|
124
|
+
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
import os
|
|
128
|
+
import numpy as np
|
|
129
|
+
import struct
|
|
130
|
+
import bz2
|
|
131
|
+
import xarray as xr
|
|
132
|
+
from datetime import datetime,timedelta
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
from multiprocessing import cpu_count, Pool,freeze_support
|
|
136
|
+
|
|
137
|
+
def _structure_size(structure):
|
|
138
|
+
""" Find the size of a structure in bytes. """
|
|
139
|
+
return struct.calcsize('<' + ''.join([i[1] for i in structure]))
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _unpack_from_buf( buf, pos, structure):
|
|
143
|
+
""" Unpack a structure from a buffer. """
|
|
144
|
+
size = _structure_size(structure)
|
|
145
|
+
return _unpack_structure(buf[pos:pos + size], structure)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _unpack_structure(string, structure):
|
|
149
|
+
""" Unpack a structure from a string """
|
|
150
|
+
fmt = '<' + ''.join([i[1] for i in structure]) # little-endian
|
|
151
|
+
lst = struct.unpack(fmt, string)
|
|
152
|
+
return dict(zip([i[0] for i in structure], lst))
|
|
153
|
+
|
|
154
|
+
def decode_mosaic(filepath,filename,minv=10,maxv = 80):
|
|
155
|
+
|
|
156
|
+
if not os.path.exists(filepath+os.sep + filename):
|
|
157
|
+
print(filepath+os.sep+filename + ' not exists!')
|
|
158
|
+
return None,None
|
|
159
|
+
try:
|
|
160
|
+
fin = open(filepath + os.sep + filename,'rb')
|
|
161
|
+
except:
|
|
162
|
+
return None,None
|
|
163
|
+
|
|
164
|
+
buf = fin.read()
|
|
165
|
+
fin.close()
|
|
166
|
+
pos = 0
|
|
167
|
+
if len(buf)==0:
|
|
168
|
+
return None
|
|
169
|
+
dic_gh = _unpack_from_buf(buf, pos, MOSAIC_HEADER)
|
|
170
|
+
pos +=_structure_size(MOSAIC_HEADER)
|
|
171
|
+
databuf = bz2.decompress(buf[pos:])
|
|
172
|
+
data = np.frombuffer(databuf, 'int16')
|
|
173
|
+
data = np.reshape(data,[dic_gh['nY'],dic_gh['nX']])
|
|
174
|
+
data=data.astype('float')
|
|
175
|
+
# data[data == -32768] = np.NAN # 空白
|
|
176
|
+
# data[data == -1280] = np.NAN # 有覆盖但无数据
|
|
177
|
+
data[data < -300] = np.NAN
|
|
178
|
+
data = np.flipud(data)/dic_gh['scale']
|
|
179
|
+
data[data < int(minv)] = np.NAN
|
|
180
|
+
data[data > int(maxv)] = np.NAN
|
|
181
|
+
|
|
182
|
+
# set longitude and latitude coordinates
|
|
183
|
+
lat = dic_gh['edge_s']/1000 + np.arange(dic_gh['nY'])*dic_gh['dy']/10000
|
|
184
|
+
lon = dic_gh['edge_w']/1000 + np.arange(dic_gh['nX'])*dic_gh['dx']/10000
|
|
185
|
+
|
|
186
|
+
# set time coordinates
|
|
187
|
+
time = datetime(dic_gh['year'],dic_gh['month'],dic_gh['day'],dic_gh['hour'],dic_gh['min'],dic_gh['sec'])
|
|
188
|
+
time = np.array([time], dtype='datetime64[m]')
|
|
189
|
+
# data = np.expand_dims(data, axis=0)
|
|
190
|
+
tmpdata = np.reshape(data, (1, data.shape[0], data.shape[1]))
|
|
191
|
+
# define coordinates
|
|
192
|
+
lev_coord = ('lev', [dic_gh['height'],], {'long_name':'height', 'units':'m', '_CoordinateAxisType':'Height'})
|
|
193
|
+
lon_coord = ('lon', lon, {
|
|
194
|
+
'long_name':'longitude', 'units':'degrees_east', '_CoordinateAxisType':'Lon'})
|
|
195
|
+
lat_coord = ('lat', lat, {
|
|
196
|
+
'long_name':'latitude', 'units':'degrees_north', '_CoordinateAxisType':'Lat'})
|
|
197
|
+
|
|
198
|
+
# create xarray
|
|
199
|
+
varattrs = {'long_name': 'Refelectivity',
|
|
200
|
+
'short_name': 'ref', 'units': 'dBZ',
|
|
201
|
+
'maxv':maxv,
|
|
202
|
+
'minv':minv}
|
|
203
|
+
data = xr.Dataset({'ref':(['lev','lat', 'lon'], tmpdata, varattrs)},coords={ 'lev':lev_coord,'lat':lat_coord, 'lon':lon_coord})
|
|
204
|
+
|
|
205
|
+
# add attributes
|
|
206
|
+
data.attrs['Conventions'] = "CF-1.6"
|
|
207
|
+
data.attrs['Origin'] = 'cmadaas'
|
|
208
|
+
data.attrs['author'] = 'ZWJ'
|
|
209
|
+
|
|
210
|
+
return data
|
|
211
|
+
|
|
212
|
+
def trans_single(param):
|
|
213
|
+
|
|
214
|
+
filepath = param['filepath']
|
|
215
|
+
filename = param['filename']
|
|
216
|
+
outpath = param['outpath']
|
|
217
|
+
pass
|
|
218
|
+
varflag = 'unknown'
|
|
219
|
+
if filename.find('CREF') > 0:
|
|
220
|
+
varflag = 'CREF000'
|
|
221
|
+
elif filename.find('QREF') > 0:
|
|
222
|
+
varflag = 'QREF000'
|
|
223
|
+
elif filename.find('_CAP_') > 0:
|
|
224
|
+
varflag = 'CAP'
|
|
225
|
+
if varflag == 'CAP':
|
|
226
|
+
outname = 'ACHN.' + varflag + '.' + filename.split('_')[4][0:8] +'.' + \
|
|
227
|
+
filename.split('_')[4][8:14] + '_' + filename.split('_')[-1].split('.')[0] + '.nc'
|
|
228
|
+
else:
|
|
229
|
+
# outname = 'ACHN.' + varflag + '.' + filename.split('_')[4][0:8] +'.' + filename.split('_')[4][8:14] + '.nc'
|
|
230
|
+
outname = 'ACHN.' + varflag + '.' + filename.split('_')[2] +'.' + filename.split('_')[3][0:6] + '.nc'
|
|
231
|
+
if os.path.exists(outpath + os.sep + outname):
|
|
232
|
+
print(outpath + os.sep + outname + ' already exists!')
|
|
233
|
+
return True
|
|
234
|
+
try:
|
|
235
|
+
data=decode_mosaic(filepath,filename,minv=0,maxv=80)
|
|
236
|
+
if data is None:
|
|
237
|
+
return False
|
|
238
|
+
datakey = list(data.keys())
|
|
239
|
+
if 'cref' not in datakey:
|
|
240
|
+
#将ref变量rename为cref
|
|
241
|
+
data=data.rename({datakey[0]:'cref'})
|
|
242
|
+
if not os.path.exists(outpath):
|
|
243
|
+
os.makedirs(outpath)
|
|
244
|
+
data.to_netcdf(outpath + os.sep + outname,encoding={'cref': {'zlib': True}})
|
|
245
|
+
print(outpath + os.sep + outname + ' done!')
|
|
246
|
+
except Exception as e:
|
|
247
|
+
print(e)
|
|
248
|
+
print(outpath + os.sep + outname + ' make error!')
|
|
249
|
+
|
|
250
|
+
# 批量转nc文件
|
|
251
|
+
def trans_bin_nc_batch(inpath,outpath,):
|
|
252
|
+
|
|
253
|
+
if not os.path.exists(inpath):
|
|
254
|
+
print(inpath + ' not exists!')
|
|
255
|
+
if not os.path.exists(outpath):
|
|
256
|
+
os.makedirs(outpath)
|
|
257
|
+
|
|
258
|
+
files = os.listdir(inpath)
|
|
259
|
+
files=sorted(files)
|
|
260
|
+
if len(files)==0:
|
|
261
|
+
print('no valid files')
|
|
262
|
+
return False
|
|
263
|
+
|
|
264
|
+
params=[]
|
|
265
|
+
for filename in files:
|
|
266
|
+
if filename.startswith('.') or filename.startswith('..'):
|
|
267
|
+
continue
|
|
268
|
+
if not filename.endswith('.bin'):
|
|
269
|
+
continue
|
|
270
|
+
curparam=dict()
|
|
271
|
+
curparam['filepath'] = inpath
|
|
272
|
+
curparam['filename'] = filename
|
|
273
|
+
curparam['outpath'] = outpath# + os.sep + filename.replace('.bin','.nc')#filename.split('_')[9][0:4]
|
|
274
|
+
params.append(curparam)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
# 多进程处理
|
|
278
|
+
MAXP = int(cpu_count()*0.6)
|
|
279
|
+
pools = Pool(MAXP)
|
|
280
|
+
|
|
281
|
+
pools.map(trans_single, params)
|
|
282
|
+
pools.close()
|
|
283
|
+
pools.join()
|
|
284
|
+
|
|
285
|
+
if __name__ == '__main__':
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
sourcepath = r'/Users/wenjianzhu/Downloads/CMADAAS/rdmosaic_bin'
|
|
289
|
+
outpath = r'/Users/wenjianzhu/Downloads/CMADAAS/mosaicdata_nc'
|
|
290
|
+
starttime = '20230701'
|
|
291
|
+
endtime = '20230702'
|
|
292
|
+
startt = datetime.strptime(starttime,'%Y%m%d')
|
|
293
|
+
endt = datetime.strptime(endtime,'%Y%m%d')
|
|
294
|
+
curt = startt
|
|
295
|
+
# ACHN.CREF000.20221001.143000.nc
|
|
296
|
+
prepath = ''
|
|
297
|
+
while curt <= endt:
|
|
298
|
+
pass
|
|
299
|
+
curpath = sourcepath + os.sep + curt.strftime('%Y%m')
|
|
300
|
+
if prepath == curpath:
|
|
301
|
+
curt = curt + timedelta(days=1)
|
|
302
|
+
continue
|
|
303
|
+
if not os.path.exists(curpath):
|
|
304
|
+
curt = curt + timedelta(days=1)
|
|
305
|
+
continue
|
|
306
|
+
|
|
307
|
+
trans_bin_nc_batch(curpath,outpath)
|
|
308
|
+
curt = curt + timedelta(days=1)
|
|
309
|
+
prepath = curpath
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
'''
|
|
2
|
+
本程序将极坐标格式的ppi数据转换为格点数据,并保存为nc格式
|
|
3
|
+
|
|
4
|
+
'''
|
|
5
|
+
|
|
6
|
+
# %%
|
|
7
|
+
import numpy as np
|
|
8
|
+
import xarray as xr
|
|
9
|
+
from decode_fmt_pyart import read_cnrad_fmt
|
|
10
|
+
import os
|
|
11
|
+
import time
|
|
12
|
+
import shutil
|
|
13
|
+
|
|
14
|
+
def do_ppi(params):
|
|
15
|
+
|
|
16
|
+
# sweep_slice,radar,outname
|
|
17
|
+
sweep_slice = params['sweep_slice']
|
|
18
|
+
target_reso = params['out_reso']
|
|
19
|
+
# print(sweep_slice)
|
|
20
|
+
radar = params['radar']
|
|
21
|
+
|
|
22
|
+
ori_reso = radar.range['meters_between_gates']
|
|
23
|
+
# target_reso = 500
|
|
24
|
+
reso_list = list(np.arange(0,11,1)*ori_reso)
|
|
25
|
+
# 从reso_list中找到最接近target_reso的值
|
|
26
|
+
out_scale = np.argmin(np.abs(np.array(reso_list)-target_reso))
|
|
27
|
+
# out_scale = int(target_reso/ori_reso)
|
|
28
|
+
target_reso = ori_reso * out_scale
|
|
29
|
+
|
|
30
|
+
# sweep_slice = slice(0,384,None)
|
|
31
|
+
sweep_azimuths = radar.azimuth['data'][sweep_slice]
|
|
32
|
+
elv = np.mean(radar.elevation['data'][sweep_slice])
|
|
33
|
+
|
|
34
|
+
# 输出的距离库只保留一半
|
|
35
|
+
ngates = int(len(radar.gate_x['data'][sweep_slice][0])/2) #//2*2
|
|
36
|
+
grid_x = np.arange(-1*ngates,ngates+1,out_scale)
|
|
37
|
+
grid_y = np.arange(-1*ngates,ngates+1,out_scale)
|
|
38
|
+
total_gates = len(grid_x)
|
|
39
|
+
|
|
40
|
+
aa = np.meshgrid(grid_x,grid_y)
|
|
41
|
+
azi_grid = np.arctan2(aa[0],aa[1])*180/np.pi
|
|
42
|
+
azi_grid[azi_grid<0]+=360
|
|
43
|
+
|
|
44
|
+
azi_reso = 360/len(sweep_azimuths)
|
|
45
|
+
|
|
46
|
+
# 求方位角索引
|
|
47
|
+
new_azi = azi_grid.flatten()
|
|
48
|
+
t = new_azi-sweep_azimuths[0]
|
|
49
|
+
t[t<0]+=360
|
|
50
|
+
ray_number = np.round(t/azi_reso,0).astype(int)
|
|
51
|
+
ray_number[ray_number==len(sweep_azimuths)]=0
|
|
52
|
+
ray_number = np.reshape(ray_number,(total_gates,total_gates))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# 求距离索引
|
|
56
|
+
dis_grid = np.sqrt(aa[0]**2 + aa[1]**2)
|
|
57
|
+
dis_grid = np.round(dis_grid.flatten(),0).astype(int)
|
|
58
|
+
dis_grid = np.reshape(dis_grid,(total_gates,total_gates))
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
sweepdata = radar.fields['reflectivity']['data'][sweep_slice]
|
|
63
|
+
# 对数据进行截断,在径向方向上
|
|
64
|
+
sweepdata = sweepdata[:,0:ngates]
|
|
65
|
+
# if np.max(sweepdata.data.flatten()) < -30:
|
|
66
|
+
# # 表示该层无有效数据
|
|
67
|
+
# return None
|
|
68
|
+
# data_grid = np.zeros((total_gates,total_gates)) - 9999
|
|
69
|
+
data_grid = np.zeros((total_gates,total_gates))
|
|
70
|
+
new_data = data_grid.flatten()
|
|
71
|
+
new_spdata = sweepdata.flatten()
|
|
72
|
+
|
|
73
|
+
pos_out = [i+j*total_gates for i in range(total_gates) for j in range(total_gates) if dis_grid[i,j] < ngates]
|
|
74
|
+
d_out = [rn*ngates+dg for rn,dg in zip(ray_number.flatten(),dis_grid.flatten()) if dg < ngates]
|
|
75
|
+
|
|
76
|
+
new_data[pos_out]=new_spdata[d_out]
|
|
77
|
+
new_data[new_data<-10]=np.nan
|
|
78
|
+
new_data[new_data>=95]=np.nan
|
|
79
|
+
new_data = new_data *2 + 64
|
|
80
|
+
new_data[np.isnan(new_data)]=255
|
|
81
|
+
new_data = new_data.astype(np.uint8)
|
|
82
|
+
data_grid = np.reshape(new_data,(total_gates,total_gates))
|
|
83
|
+
outdic={'data':data_grid.transpose(),'elv':elv,'tol_gates':total_gates,
|
|
84
|
+
'out_reso':target_reso,'datatype':'uint8','scale_factor':2,'add_offset':64,
|
|
85
|
+
'missing_value':255}
|
|
86
|
+
print('ele: ' + str(elv) + ' done!')
|
|
87
|
+
|
|
88
|
+
del data_grid,new_data,new_spdata,pos_out,d_out,sweepdata
|
|
89
|
+
return outdic
|
|
90
|
+
|
|
91
|
+
def do_radar(param):
|
|
92
|
+
pass
|
|
93
|
+
try:
|
|
94
|
+
filename = param['filename']
|
|
95
|
+
outname = param['outname']
|
|
96
|
+
out_reso = param['out_reso']
|
|
97
|
+
if 'bcopy' in param.keys():
|
|
98
|
+
bcopy = param['bcopy']
|
|
99
|
+
else:
|
|
100
|
+
bcopy = 0
|
|
101
|
+
if 'outpath2' in param.keys():
|
|
102
|
+
outpath2 = param['outpath2']
|
|
103
|
+
else:
|
|
104
|
+
outpath2 = ''
|
|
105
|
+
print('outpath2 not set!')
|
|
106
|
+
print('start trans ' + filename)
|
|
107
|
+
|
|
108
|
+
# 读取雷达数据
|
|
109
|
+
radar = read_cnrad_fmt(filename)
|
|
110
|
+
|
|
111
|
+
if 'reflectivity' in radar.fields.keys():
|
|
112
|
+
print('ref in data!')
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
start = time.time()
|
|
116
|
+
|
|
117
|
+
all_data = []
|
|
118
|
+
elvs = []
|
|
119
|
+
|
|
120
|
+
nnf=0
|
|
121
|
+
pre_ele=-999
|
|
122
|
+
for sweep_slice in radar.iter_slice():
|
|
123
|
+
# if nnf ==2:
|
|
124
|
+
# break
|
|
125
|
+
params={'sweep_slice':sweep_slice,'radar':radar,'out_reso':out_reso,}
|
|
126
|
+
cur_ele = np.mean(radar.elevation['data'][sweep_slice])
|
|
127
|
+
if abs(cur_ele - pre_ele) < 0.2:
|
|
128
|
+
# print('该仰角已处理过!')
|
|
129
|
+
# 实际上是跳过了最低仰角的两层径向速度
|
|
130
|
+
continue
|
|
131
|
+
|
|
132
|
+
outdic = do_ppi(params)
|
|
133
|
+
if outdic is None:
|
|
134
|
+
continue
|
|
135
|
+
all_data.append(outdic['data'])
|
|
136
|
+
elvs.append(outdic['elv'])
|
|
137
|
+
pre_ele = cur_ele
|
|
138
|
+
nnf +=1
|
|
139
|
+
end = time.time()
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
#构建xarray数据
|
|
143
|
+
total_gates = outdic['tol_gates']
|
|
144
|
+
if total_gates % 2 == 0:
|
|
145
|
+
out_grid = np.arange(int(-total_gates/2),int(total_gates/2))
|
|
146
|
+
else:
|
|
147
|
+
out_grid = np.arange(int(-(total_gates-1)/2),int((total_gates-1)/2)+1)
|
|
148
|
+
|
|
149
|
+
if len(all_data) == 0:
|
|
150
|
+
print('no data in ' + filename)
|
|
151
|
+
|
|
152
|
+
return
|
|
153
|
+
all_data = np.array(all_data)
|
|
154
|
+
all_data = all_data.astype(np.uint8)
|
|
155
|
+
data = xr.DataArray(np.array(all_data),coords=[elvs,out_grid,out_grid],dims=['z','x','y'],name='ref')
|
|
156
|
+
data.attrs['units'] = 'dBZ'
|
|
157
|
+
data.attrs['standard_name'] = 'equivalent_reflectivity_factor'
|
|
158
|
+
data.attrs['long_name'] = 'equivalent_reflectivity_factor'
|
|
159
|
+
data.attrs['radar_lat'] = radar.latitude['data'][0]
|
|
160
|
+
data.attrs['radar_lon'] = radar.longitude['data'][0]
|
|
161
|
+
data.attrs['radar_altitude'] = radar.altitude['data'][0]
|
|
162
|
+
data.attrs['grid_num'] = total_gates
|
|
163
|
+
data.attrs['grid_reso'] = outdic['out_reso']
|
|
164
|
+
data.attrs['elevation'] = elvs
|
|
165
|
+
data.attrs['obs_range'] = int(outdic['out_reso'] * (total_gates-1)/2)
|
|
166
|
+
data.attrs['distance_unit'] = 'meter'
|
|
167
|
+
data.attrs['missing_value'] = 255
|
|
168
|
+
data.attrs['scale_factor'] = 2
|
|
169
|
+
data.attrs['add_offset'] = 64
|
|
170
|
+
data.attrs['datatype'] = 'uint8'
|
|
171
|
+
data.attrs['decode_method'] = 'dbz = (data - add_offset) / scale_factor'
|
|
172
|
+
|
|
173
|
+
if not os.path.exists(os.path.dirname(outname)):
|
|
174
|
+
os.makedirs(os.path.dirname(outname))
|
|
175
|
+
|
|
176
|
+
data.to_netcdf(outname,encoding={'ref': {'zlib': True,'dtype':'uint8'},})
|
|
177
|
+
print(outname + ' saved!')
|
|
178
|
+
|
|
179
|
+
# copy to outpath2
|
|
180
|
+
if bcopy == 1:
|
|
181
|
+
if not os.path.exists(outpath2):
|
|
182
|
+
os.makedirs(outpath2)
|
|
183
|
+
shutil.copy(outname,outpath2 + os.sep + os.path.basename(outname))
|
|
184
|
+
print(outpath2 + os.sep + os.path.basename(outname) + ' copied!')
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
except Exception as e:
|
|
188
|
+
print(e)
|
|
189
|
+
|
|
190
|
+
if __name__ == "__main__":
|
|
191
|
+
rootpath = 'testdata/FMT/'
|
|
192
|
+
filename = 'Z_RADR_I_Z9200_20240831130000_O_DOR_SAD_CAP_FMT.bin.bz2'
|
|
193
|
+
|
|
194
|
+
outname = '/Users/wenjianzhu/Downloads/polargrid/' + filename + '_new.nc'
|
|
195
|
+
params={'filename':rootpath + filename,'outname':outname,'out_reso':500,'bcopy':0}
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
st = time.time()
|
|
199
|
+
do_radar(params)
|
|
200
|
+
et = time.time()
|
|
201
|
+
print(et-st)
|
|
202
|
+
|
|
203
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: metradar
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: radar data processing
|
|
5
|
+
Author-email: Wenjian Zhu <kevin2075@163.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: numpy>=1.18
|
|
12
|
+
Requires-Dist: requests>=2.24.0
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
metradar/__init__.py,sha256=K7a1zThYS0yYHgWTDHbJ5jcIHZVtm5_RYwkzcKEWi0g,183
|
|
2
|
+
metradar/cnrad_level2.py,sha256=vy4d-CCAigJGZrm-Dr3_NsmzSs1Tg_ufQvVSZSH57ic,44916
|
|
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
|
+
metradar/decode_fmt_pyart.py,sha256=Fjl6tSr53AUnir_HeDEOD0zQ8kuA5kPzWo-77zaWsiY,7542
|
|
9
|
+
metradar/decode_pup_rose.py,sha256=d5ajuJuM6X8kCiNGUBOrCeub6j2K9Y-Qgvjq4H-Qemc,82826
|
|
10
|
+
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
|
+
metradar/draw_radar_comp_func.py,sha256=Hc7TtZMLobW4VCPYPlYyq5MarVYBYDqgBhVJrYMgcHI,63969
|
|
13
|
+
metradar/exceptions.py,sha256=C5jsADZix3E6Ah1sUPyBtgrGygy69lFc0QD5wO07a00,1300
|
|
14
|
+
metradar/geo_transforms_pyart.py,sha256=7yOJOVLUaBnUQiesgvKZuESSNOx1uEYDilcRQAw5avM,21941
|
|
15
|
+
metradar/get_cross_section_from_pyart.py,sha256=x4fSAUa8AzhuXsn48lvduA1ELlL-L7wZQZq8r4FniyU,11662
|
|
16
|
+
metradar/get_tlogp_from_sharppy.py,sha256=oYGFOHjkSbeRYS4yFXk9APfTsuqN3CxUVuv5xR6TUAs,2832
|
|
17
|
+
metradar/grid.py,sha256=2ARummd819SCjWi87toZgOZ0A8obcIUFfAmRV-11EU0,11165
|
|
18
|
+
metradar/grid_data.py,sha256=9e4-x_82ZwcwtjRM6BWUGWQXfg1PhuAH3F59OAd8wxo,1878
|
|
19
|
+
metradar/main_pydda.py,sha256=i32-YF0ebm4im7UkQcUXKcz0TJvRscunzdxSsz56gqU,28659
|
|
20
|
+
metradar/make_gif.py,sha256=rDNqhZXKAyQB_B2adU-ven07QgOTXwdY6eRFVsjTrdI,563
|
|
21
|
+
metradar/make_mosaic_mp_archive.py,sha256=AXiTSSOL1ik0aLy-u4B_LjO4-sPVinhBqkTtPcMVlYI,19556
|
|
22
|
+
metradar/mosaic_merge.py,sha256=eTTBJ5w2LchMBhjMHp1g97PGVcSzadoSKQwgtqjE4-M,1628
|
|
23
|
+
metradar/mosaic_quickdraw.py,sha256=k0WI5hUKifCNSlbMrS8oJSBuM5XjWu5QDOkXoR50wFI,11910
|
|
24
|
+
metradar/nowcast_by_pysteps.py,sha256=OcDY5Gb0pd1EM4pPD-bhIpoln3bH3aZ74J4DTCa4INk,7250
|
|
25
|
+
metradar/oa_couhua.py,sha256=Gs85Lf1s5zuVdUQ3cuVUVF_h5KAQHOoNsQU4nvyUdHs,4414
|
|
26
|
+
metradar/oa_dig_func.py,sha256=k3myqBg8jM901vrpKVZWgEL3RvZ06yQLJPV7O3l0Lng,34342
|
|
27
|
+
metradar/parse_pal.py,sha256=dtF0hwXNoRFVHQygRs8lUePHPVRfoCvwvdAl1gRPjwg,5072
|
|
28
|
+
metradar/pgmb_io.py,sha256=4D7beTSazhKTAzGwsQHaTxSn6PMqJpF4oOmMDIMuGio,5459
|
|
29
|
+
metradar/prepare_for_radar_draw.py,sha256=59PRnUZ0olef272z8yYl8cC8H7lRQTRQc2VUhaTQXY8,6512
|
|
30
|
+
metradar/read_new_mosaic.py,sha256=zE5Se0One0ev0mKn-_YOw3TfNf-ATPVGA8wVZg3_zbo,1205
|
|
31
|
+
metradar/read_new_mosaic_func.py,sha256=dw_-b3H5n49G47PHbEtAxboECIgt28MLyZc0leLcAIs,7259
|
|
32
|
+
metradar/retrieve_cmadaas.py,sha256=apwhisjHKfN6keahMgn73cVcA9jmEFGPOEmd6iX-xXc,137463
|
|
33
|
+
metradar/retrieve_micaps_server.py,sha256=cb-a_OKM1zCSw0tZ_Gk7RofE16RiRX6qq3oTUQt7lMc,85607
|
|
34
|
+
metradar/rose_structer.py,sha256=3EAZ18OXg0FXR4U1DNEvwU4gxP8mSRGkGUKjAW85IPs,25293
|
|
35
|
+
metradar/trans_nc_pgmb.py,sha256=EfjaswKix4f8G-T1O6UKJ8lX9F_8z_IILucX_R2xdSk,1738
|
|
36
|
+
metradar/trans_new_mosaic_nc.py,sha256=dZPr625hV7msFOgUVPwFgjTrTgQOEsIywMABzansPYA,9705
|
|
37
|
+
metradar/trans_polor2grid_func.py,sha256=Ad6Ii_Ew3dwbRmN7RrRpDD-wU33xm7jbZAJbIVM3EsI,6864
|
|
38
|
+
metradar-0.1.0.dist-info/METADATA,sha256=Tm0STHZgVcIUibDsffJQQN8IjkKwKOpHDW9lVIO3NPo,398
|
|
39
|
+
metradar-0.1.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
40
|
+
metradar-0.1.0.dist-info/top_level.txt,sha256=vwxtTxux8rWm6wgfnwf0YWYrWjN16TZQCOy4h_OVwoE,9
|
|
41
|
+
metradar-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
metradar
|