@@ -208,17 +208,13 @@ def __init__(self, file: Any, product: Optional[str] = None):
208
208
header ["y_grid_num" ][0 ],
209
209
header ["z_grid_num" ][0 ],
210
210
)
211
+ self .heights = header ["height" ][0 ][:zdim ]
211
212
dtype = header ["m_data_type" ][0 ]
212
213
data_size = int (xdim ) * int (ydim ) * int (zdim ) * self .size_conv [dtype ]
213
214
bittype = self .dtype_conv [dtype ]
214
215
data_body = np .frombuffer (f .read (data_size ), bittype ).astype (int )
215
216
# Convert data to i4 to avoid overflow in later calculation
216
- if zdim == 1 :
217
- # 2D data
218
- out = data_body .reshape (ydim , xdim )
219
- else :
220
- # 3D data
221
- out = data_body .reshape (zdim , ydim , xdim )
217
+ out = data_body .reshape (zdim , ydim , xdim )
222
218
self .data_time = datetime .datetime (
223
219
header ["year" ][0 ],
224
220
header ["month" ][0 ],
@@ -227,15 +223,14 @@ def __init__(self, file: Any, product: Optional[str] = None):
227
223
header ["minute" ][0 ],
228
224
)
229
225
# TODO: Recognize correct product name
230
- product_name = (
226
+ self . product_name = (
231
227
(b"" .join (header ["data_name" ]).decode ("gbk" , "ignore" ).replace ("\x00 " , "" ))
232
228
if not product
233
229
else product
234
230
)
235
- self .product_name = product_name
236
- for pname in ["CR" , "3DREF" ]:
237
- if product_name .startswith (pname ):
238
- self .product_name = pname
231
+ for pname in ["CR" , "3DREF" , "反射率" ]:
232
+ if pname in self .product_name :
233
+ self .product_name = "CR"
239
234
start_lon = header ["start_lon" ][0 ]
240
235
start_lat = header ["start_lat" ][0 ]
241
236
center_lon = header ["center_lon" ][0 ]
@@ -246,13 +241,13 @@ def __init__(self, file: Any, product: Optional[str] = None):
246
241
# y_reso = header['y_reso'][0]
247
242
self .lon = np .linspace (start_lon , end_lon , xdim ) # For shape compatibility
248
243
self .lat = np .linspace (start_lat , end_lat , ydim )
249
- if self .product_name in [ "CR" , "3DREF" ] :
244
+ if self .product_name == "CR" :
250
245
self .data = (np .ma .masked_equal (out , 0 ) - 66 ) / 2
251
246
else :
252
247
# Leave data unchanged because the scale and offset are unclear
253
248
self .data = np .ma .masked_equal (out , 0 )
254
249
255
- def get_data (self , level : int = 0 ) -> Dataset :
250
+ def get_data (self ) -> Dataset :
256
251
r"""
257
252
Get radar data with extra information
258
253
@@ -262,16 +257,13 @@ def get_data(self, level: int = 0) -> Dataset:
262
257
Returns:
263
258
xarray.Dataset: Data.
264
259
"""
265
- dtype = self .product_name
266
- if self .data .ndim == 2 :
267
- ret = self .data
268
- else :
269
- ret = self .data [level ]
270
- if self .product_name == "3DREF" :
271
- dtype = "CR"
272
- da = DataArray (ret , coords = [self .lat , self .lon ], dims = ["latitude" , "longitude" ])
260
+ da = DataArray (
261
+ self .data ,
262
+ coords = [self .heights , self .lat , self .lon ],
263
+ dims = ["height" , "latitude" , "longitude" ],
264
+ )
273
265
ds = Dataset (
274
- {dtype : da },
266
+ {self . product_name : da },
275
267
attrs = {
276
268
"scan_time" : self .data_time .strftime ("%Y-%m-%d %H:%M:%S" ),
277
269
"site_code" : "SWAN" ,
@@ -281,6 +273,8 @@ def get_data(self, level: int = 0) -> Dataset:
281
273
"elevation" : 0 ,
282
274
},
283
275
)
276
+ if len (self .heights ) == 1 :
277
+ ds = ds .squeeze ("height" )
284
278
return ds
285
279
286
280
@@ -518,13 +512,17 @@ def _parse_header(self):
518
512
if header ["magic_number" ] != 0x4D545352 :
519
513
raise RadarDecodeError ("Invalid standard data" )
520
514
site_config = np .frombuffer (self .f .read (128 ), SDD_site )
521
- self .code = site_config ["site_code" ][0 ].decode ().replace ("\x00 " , "" )
515
+ self .code = (
516
+ site_config ["site_code" ][0 ].decode ("ascii" , "ignore" ).replace ("\x00 " , "" )
517
+ )
522
518
self .geo = geo = dict ()
523
519
geo ["lat" ] = site_config ["Latitude" ]
524
520
geo ["lon" ] = site_config ["Longitude" ]
525
521
geo ["height" ] = site_config ["ground_height" ]
526
522
task = np .frombuffer (self .f .read (256 ), SDD_task )
527
- self .task_name = task ["task_name" ][0 ].decode ().replace ("\x00 " , "" )
523
+ self .task_name = (
524
+ task ["task_name" ][0 ].decode ("ascii" , "ignore" ).replace ("\x00 " , "" )
525
+ )
528
526
cut_num = task ["cut_number" ][0 ]
529
527
self .scan_config = np .frombuffer (self .f .read (256 * cut_num ), SDD_cut )
530
528
ph = np .frombuffer (self .f .read (128 ), SDD_pheader )
@@ -572,7 +570,7 @@ def _parse_radial_fmt(self):
572
570
az [az > 360 ] -= 360
573
571
azi = az * deg2rad
574
572
# self.azi = np.deg2rad(azi)
575
- dist = np .arange (start_range + reso , end_range + reso , reso )
573
+ dist = np .arange (start_range // reso + 1 , end_range // reso + 1 , 1 ) * reso
576
574
lon , lat = get_coordinate (
577
575
dist , azi , self .params ["elevation" ], self .stationlon , self .stationlat
578
576
)
@@ -1061,6 +1059,14 @@ class MocMosaic(object):
1061
1059
解析中国气象局探测中心-天气雷达拼图系统V3.0-产品
1062
1060
"""
1063
1061
1062
+ dtype_conv = [
1063
+ ("QREF" , "REF" ),
1064
+ ("CREF" , "CR" ),
1065
+ ("CRF" , "CR" ),
1066
+ ("CAP" , "REF" ),
1067
+ ("UCR" , "CR" ),
1068
+ ]
1069
+
1064
1070
def __init__ (self , file ):
1065
1071
self .f = prepare_file (file )
1066
1072
radartype = self ._check_ftype ()
@@ -1151,6 +1157,10 @@ def _parse_single(self):
1151
1157
r = np .reshape (out_data , (len (out_data ), self .ny , self .nx ))
1152
1158
ret = np .flipud (r ) # Data store reverse in y axis
1153
1159
data = (np .ma .masked_less (ret , 0 )) / self .scale
1160
+ for oname , cname in self .dtype_conv :
1161
+ if self .dtype == oname :
1162
+ self .dtype = cname
1163
+ break
1154
1164
da = DataArray (
1155
1165
data ,
1156
1166
coords = [heights , self .lat , self .lon ],
@@ -1170,6 +1180,8 @@ def _parse_single(self):
1170
1180
"task" : "VCP{}" .format (self .vcp ),
1171
1181
},
1172
1182
)
1183
+ if len (heights ) == 1 :
1184
+ ds = ds .squeeze ("height" )
1173
1185
self ._dataset = ds
1174
1186
1175
1187
def _parse_mosaic (self ):
@@ -1198,7 +1210,7 @@ def _parse_mosaic(self):
1198
1210
)
1199
1211
self .lon = np .linspace (edge_w , edge_e , nx )
1200
1212
self .lat = np .linspace (edge_s , edge_n , ny )
1201
- databody = self .f .read (nx * ny * 2 )
1213
+ databody = self .f .read ()
1202
1214
if compress == 0 :
1203
1215
databody = databody
1204
1216
elif compress == 1 :
@@ -1210,6 +1222,10 @@ def _parse_mosaic(self):
1210
1222
out = np .frombuffer (databody , "i2" ).astype (int ).reshape (ny , nx )
1211
1223
out = np .flipud (out )
1212
1224
self .data = (np .ma .masked_less (out , 0 )) / scale
1225
+ for oname , cname in self .dtype_conv :
1226
+ if self .dtype == oname :
1227
+ self .dtype = cname
1228
+ break
1213
1229
da = DataArray (
1214
1230
self .data , coords = [self .lat , self .lon ], dims = ["latitude" , "longitude" ]
1215
1231
)
0 commit comments