Skip to content

Commit f15756d

Browse files
authored
fix: SWAN dtype name and height dimension & StandardPUP range (#119)
* fix:StandardPUP&MocMosaic bugs * fix SWAN & MocMosaic dtype name and update dim of height
1 parent 0369d5f commit f15756d

File tree

1 file changed

+42
-26
lines changed

1 file changed

+42
-26
lines changed

cinrad/io/level3.py

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -208,17 +208,13 @@ def __init__(self, file: Any, product: Optional[str] = None):
208208
header["y_grid_num"][0],
209209
header["z_grid_num"][0],
210210
)
211+
self.heights = header["height"][0][:zdim]
211212
dtype = header["m_data_type"][0]
212213
data_size = int(xdim) * int(ydim) * int(zdim) * self.size_conv[dtype]
213214
bittype = self.dtype_conv[dtype]
214215
data_body = np.frombuffer(f.read(data_size), bittype).astype(int)
215216
# 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)
222218
self.data_time = datetime.datetime(
223219
header["year"][0],
224220
header["month"][0],
@@ -227,15 +223,14 @@ def __init__(self, file: Any, product: Optional[str] = None):
227223
header["minute"][0],
228224
)
229225
# TODO: Recognize correct product name
230-
product_name = (
226+
self.product_name = (
231227
(b"".join(header["data_name"]).decode("gbk", "ignore").replace("\x00", ""))
232228
if not product
233229
else product
234230
)
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"
239234
start_lon = header["start_lon"][0]
240235
start_lat = header["start_lat"][0]
241236
center_lon = header["center_lon"][0]
@@ -246,13 +241,13 @@ def __init__(self, file: Any, product: Optional[str] = None):
246241
# y_reso = header['y_reso'][0]
247242
self.lon = np.linspace(start_lon, end_lon, xdim) # For shape compatibility
248243
self.lat = np.linspace(start_lat, end_lat, ydim)
249-
if self.product_name in ["CR", "3DREF"]:
244+
if self.product_name == "CR":
250245
self.data = (np.ma.masked_equal(out, 0) - 66) / 2
251246
else:
252247
# Leave data unchanged because the scale and offset are unclear
253248
self.data = np.ma.masked_equal(out, 0)
254249

255-
def get_data(self, level: int = 0) -> Dataset:
250+
def get_data(self) -> Dataset:
256251
r"""
257252
Get radar data with extra information
258253
@@ -262,16 +257,13 @@ def get_data(self, level: int = 0) -> Dataset:
262257
Returns:
263258
xarray.Dataset: Data.
264259
"""
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+
)
273265
ds = Dataset(
274-
{dtype: da},
266+
{self.product_name: da},
275267
attrs={
276268
"scan_time": self.data_time.strftime("%Y-%m-%d %H:%M:%S"),
277269
"site_code": "SWAN",
@@ -281,6 +273,8 @@ def get_data(self, level: int = 0) -> Dataset:
281273
"elevation": 0,
282274
},
283275
)
276+
if len(self.heights) == 1:
277+
ds = ds.squeeze("height")
284278
return ds
285279

286280

@@ -518,13 +512,17 @@ def _parse_header(self):
518512
if header["magic_number"] != 0x4D545352:
519513
raise RadarDecodeError("Invalid standard data")
520514
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+
)
522518
self.geo = geo = dict()
523519
geo["lat"] = site_config["Latitude"]
524520
geo["lon"] = site_config["Longitude"]
525521
geo["height"] = site_config["ground_height"]
526522
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+
)
528526
cut_num = task["cut_number"][0]
529527
self.scan_config = np.frombuffer(self.f.read(256 * cut_num), SDD_cut)
530528
ph = np.frombuffer(self.f.read(128), SDD_pheader)
@@ -572,7 +570,7 @@ def _parse_radial_fmt(self):
572570
az[az > 360] -= 360
573571
azi = az * deg2rad
574572
# 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
576574
lon, lat = get_coordinate(
577575
dist, azi, self.params["elevation"], self.stationlon, self.stationlat
578576
)
@@ -1061,6 +1059,14 @@ class MocMosaic(object):
10611059
解析中国气象局探测中心-天气雷达拼图系统V3.0-产品
10621060
"""
10631061

1062+
dtype_conv = [
1063+
("QREF", "REF"),
1064+
("CREF", "CR"),
1065+
("CRF", "CR"),
1066+
("CAP", "REF"),
1067+
("UCR", "CR"),
1068+
]
1069+
10641070
def __init__(self, file):
10651071
self.f = prepare_file(file)
10661072
radartype = self._check_ftype()
@@ -1151,6 +1157,10 @@ def _parse_single(self):
11511157
r = np.reshape(out_data, (len(out_data), self.ny, self.nx))
11521158
ret = np.flipud(r) # Data store reverse in y axis
11531159
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
11541164
da = DataArray(
11551165
data,
11561166
coords=[heights, self.lat, self.lon],
@@ -1170,6 +1180,8 @@ def _parse_single(self):
11701180
"task": "VCP{}".format(self.vcp),
11711181
},
11721182
)
1183+
if len(heights) == 1:
1184+
ds = ds.squeeze("height")
11731185
self._dataset = ds
11741186

11751187
def _parse_mosaic(self):
@@ -1198,7 +1210,7 @@ def _parse_mosaic(self):
11981210
)
11991211
self.lon = np.linspace(edge_w, edge_e, nx)
12001212
self.lat = np.linspace(edge_s, edge_n, ny)
1201-
databody = self.f.read(nx * ny * 2)
1213+
databody = self.f.read()
12021214
if compress == 0:
12031215
databody = databody
12041216
elif compress == 1:
@@ -1210,6 +1222,10 @@ def _parse_mosaic(self):
12101222
out = np.frombuffer(databody, "i2").astype(int).reshape(ny, nx)
12111223
out = np.flipud(out)
12121224
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
12131229
da = DataArray(
12141230
self.data, coords=[self.lat, self.lon], dims=["latitude", "longitude"]
12151231
)

0 commit comments

Comments
 (0)