Skip to content

Commit ab803cc

Browse files
committed
Read missing Sentinel V instrument data packets
1 parent dcda359 commit ab803cc

File tree

3 files changed

+257
-45
lines changed

3 files changed

+257
-45
lines changed

mhkit/dolfyn/io/base.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ def _create_dataset(data):
298298
"data": data["data_vars"][key],
299299
}
300300

301-
elif "b5" in tg:
301+
elif "b5" in key:
302302
ds_dict[key] = {
303303
"dims": ("range_b5", "time_b5"),
304304
"data": data["data_vars"][key],
@@ -324,7 +324,7 @@ def _create_dataset(data):
324324
# "vel_b5" sometimes stored as (1, range_b5, time_b5)
325325
ds_dict[key] = {
326326
"dims": ("range_b5", "time_b5"),
327-
"data": data["data_vars"][key][0],
327+
"data": data["data_vars"][key].squeeze(),
328328
}
329329
elif "sl" in key:
330330
ds_dict[key] = {
@@ -357,12 +357,12 @@ def _create_dataset(data):
357357
r_list = [r for r in ds.coords if "range" in r]
358358
for ky in r_list:
359359
ds[ky].attrs["units"] = "m"
360-
ds[ky].attrs["long_name"] = "Profile Range"
360+
ds[ky].attrs["long_name"] = "Profile " + ky.capitalize().replace("_", " ")
361361
ds[ky].attrs["description"] = "Distance to the center of each depth bin"
362362
time_list = [t for t in ds.coords if "time" in t]
363363
for ky in time_list:
364364
ds[ky].attrs["units"] = "seconds since 1970-01-01 00:00:00"
365-
ds[ky].attrs["long_name"] = "Time"
365+
ds[ky].attrs["long_name"] = ky.capitalize().replace("_", " ")
366366
ds[ky].attrs["standard_name"] = "time"
367367

368368
# Set dataset metadata

mhkit/dolfyn/io/rdi.py

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,9 @@ def load_data(self, nens=None):
323323
# reset flag after all variables run
324324
self.n_cells_diff = 0
325325

326+
# b5 clock flag
327+
b5 = True if "ping_offset_time_b5" in cfg else False
328+
326329
# Set clock
327330
clock = en.rtc[:, :]
328331
if clock[0, 0] < 100:
@@ -340,8 +343,14 @@ def load_data(self, nens=None):
340343
)
341344
)
342345
dat["coords"]["time"][iens] = np.nan
346+
if b5:
347+
dat["coords"]["time_b5"][iens] = np.nan
343348
else:
344349
dat["coords"]["time"][iens] = np.median(dates)
350+
if b5:
351+
dat["coords"]["time_b5"][iens] = (
352+
np.median(dates) + cfg["ping_offset_time_b5"]
353+
)
345354

346355
# Finalize dataset (runs through both NB and BB)
347356
for dat, cfg in zip(datl, cfgl):
@@ -587,6 +596,10 @@ def read_dat(self, id):
587596
0: (defs.read_fixed, [False]),
588597
# 0001 2nd profile fixed leader
589598
1: (defs.read_fixed, [True]),
599+
# 000B Wave parameters
600+
11: (defs.skip_Nbyte, [51]),
601+
# 000C Wave parameters - sea and swell
602+
12: (defs.skip_Nbyte, [44]),
590603
# 0010 Surface layer fixed leader (RiverPro & StreamPro)
591604
16: (defs.read_fixed_sl, []),
592605
# 0080 1st profile variable leader
@@ -639,13 +652,13 @@ def read_dat(self, id):
639652
1793: (defs.skip_Ncol, [4]), # 0701 number of pings
640653
1794: (defs.skip_Ncol, [4]), # 0702 sum of squared vel
641654
1795: (defs.skip_Ncol, [4]), # 0703 sum of velocities
642-
2560: (defs.skip_Ncol, []), # 0A00 Beam 5 velocity TODO
643-
2816: (defs.skip_Ncol, []), # 0B00 Beam 5 correlation TODO
644-
3072: (defs.skip_Ncol, []), # 0C00 Beam 5 amplitude TODO
645-
3328: (defs.skip_Ncol, []), # 0D00 Beam 5 pct_good TODO
655+
2560: (defs.read_vel_b5, []), # 0A00 Beam 5 velocity TODO
656+
2816: (defs.read_corr_b5, []), # 0B00 Beam 5 correlation TODO
657+
3072: (defs.read_amp_b5, []), # 0C00 Beam 5 amplitude TODO
658+
3328: (defs.read_prcnt_gd_b5, []), # 0D00 Beam 5 pct_good TODO
646659
# Fixed attitude data format for Ocean Surveyor ADCPs
647660
3000: (defs.skip_Nbyte, [32]),
648-
3841: (defs.skip_Nbyte, [38]), # 0F01 Beam 5 leader
661+
3841: (defs.read_vel_b5_leader, []), # 0F01 Beam 5 leader TODO
649662
8192: (defs.read_vmdas, []), # 2000
650663
# 2013 Navigation parameter data
651664
8211: (defs.skip_Nbyte, [83]),
@@ -675,16 +688,16 @@ def read_dat(self, id):
675688
22785: (defs.skip_Nbyte, [65]),
676689
# 5902 Ping attitude
677690
22786: (defs.skip_Nbyte, [105]),
678-
# 7000 Sentinvel V system configuration TODO
679-
28672: (defs.skip_Nbyte, [14]),
680-
# 7001 Sentinel V leader TODO
681-
28673: (defs.skip_Nbyte, [42]),
691+
# 7000 Sentinvel V system configuration
692+
28672: (defs.read_sentinelv_syscfg, [False]),
693+
# 7001 Sentinel V leader
694+
28673: (defs.read_sentinelv_ping_setup, [False]),
682695
# 7002 ADC data
683696
28674: (defs.skip_Nbyte, [14]),
684697
# 7003 Sentinel V "Features" (only first ensemble)
685698
28675: (defs.skip_Nbyte, [88]), # min size
686699
# 7004 Sentinel V Event Log
687-
28676: (defs.skip_Nbyte, [6]), # min size
700+
28676: (defs.read_sentinelv_event_log, []),
688701
}
689702
# Call the correct function:
690703
if self._debug_level > 1:
@@ -908,6 +921,12 @@ def cleanup(self, dat, cfg):
908921
).astype(np.float32)
909922
cfg["range_offset"] = round(bin1_dist - cfg["blank_dist"] - cfg["cell_size"], 3)
910923

924+
if "n_cells_b5" in cfg:
925+
bin1_dist_b5 = cfg.pop("bin1_dist_b5_m")
926+
dat["coords"]["range_b5"] = (
927+
bin1_dist_b5 + np.arange(cfg["n_cells_b5"]) * cfg["cell_size_b5"]
928+
).astype(np.float32)
929+
911930
# Clean up surface layer profiles
912931
if "surface_layer" in cfg: # RiverPro/StreamPro
913932
# Set SL cell size and range
@@ -1021,24 +1040,22 @@ def finalize(self, dat, cfg):
10211040
for nm in set(defs.data_defs.keys()) - self.vars_read:
10221041
lib._pop(dat, nm)
10231042

1024-
# VMDAS and WinRiver have different set sampling frequency
1025-
if ("sourceprog" in cfg) and (
1026-
cfg["sourceprog"].lower() in ["vmdas", "winriver", "winriver2"]
1027-
):
1043+
# Need to figure out how to differentiate burst mode from averaging mode
1044+
if (
1045+
("source_program" in cfg)
1046+
and (cfg["source_program"].lower() in ["vmdas", "winriver", "winriver2"])
1047+
) or ("sentinelv" in cfg["inst_model"].lower()):
10281048
cfg["fs"] = round(1 / np.median(np.diff(dat["coords"]["time"])), 2)
10291049
else:
1030-
sec_bt_ping_group = cfg["sec_between_ping_groups"]
1031-
if not sec_bt_ping_group:
1032-
cfg["fs"] = np.nan
1033-
else:
1034-
cfg["fs"] = 1 / (sec_bt_ping_group * cfg["pings_per_ensemble"])
1050+
cfg["fs"] = 1 / (cfg["sec_between_ping_groups"] * cfg["pings_per_ensemble"])
10351051

10361052
# Save configuration data as attributes
10371053
dat["attrs"] = cfg
10381054

1055+
# Set 3D variable axes properly (beam, range, time)
10391056
for nm in defs.data_defs:
10401057
shp = defs.data_defs[nm][0]
1041-
if len(shp) and shp[0] == "nc" and lib._in_group(dat, nm):
1058+
if (len(shp) == 2) and (shp[0] == "nc") and lib._in_group(dat, nm):
10421059
lib._setd(dat, nm, np.swapaxes(lib._get(dat, nm), 0, 1))
10431060

10441061
return dat

0 commit comments

Comments
 (0)