diff --git a/examples/data/dolfyn/sentinelv_b5.pd0 b/examples/data/dolfyn/sentinelv_b5.pd0 new file mode 100644 index 00000000..ac738ccc Binary files /dev/null and b/examples/data/dolfyn/sentinelv_b5.pd0 differ diff --git a/examples/data/dolfyn/test_data/RDI_7f79.nc b/examples/data/dolfyn/test_data/RDI_7f79.nc index f71b4341..a43b3d7b 100644 Binary files a/examples/data/dolfyn/test_data/RDI_7f79.nc and b/examples/data/dolfyn/test_data/RDI_7f79.nc differ diff --git a/examples/data/dolfyn/test_data/RDI_7f79_2.nc b/examples/data/dolfyn/test_data/RDI_7f79_2.nc index d794b1f4..618447a7 100644 Binary files a/examples/data/dolfyn/test_data/RDI_7f79_2.nc and b/examples/data/dolfyn/test_data/RDI_7f79_2.nc differ diff --git a/examples/data/dolfyn/test_data/RDI_test01.nc b/examples/data/dolfyn/test_data/RDI_test01.nc index cec11b0b..b930e959 100644 Binary files a/examples/data/dolfyn/test_data/RDI_test01.nc and b/examples/data/dolfyn/test_data/RDI_test01.nc differ diff --git a/examples/data/dolfyn/test_data/RDI_test01_clean.nc b/examples/data/dolfyn/test_data/RDI_test01_clean.nc index 26b8389c..d0599d26 100644 Binary files a/examples/data/dolfyn/test_data/RDI_test01_clean.nc and b/examples/data/dolfyn/test_data/RDI_test01_clean.nc differ diff --git a/examples/data/dolfyn/test_data/RDI_test01_ofilt.nc b/examples/data/dolfyn/test_data/RDI_test01_ofilt.nc index d83facf1..cf04013d 100644 Binary files a/examples/data/dolfyn/test_data/RDI_test01_ofilt.nc and b/examples/data/dolfyn/test_data/RDI_test01_ofilt.nc differ diff --git a/examples/data/dolfyn/test_data/RDI_test01_rotate_beam2inst.nc b/examples/data/dolfyn/test_data/RDI_test01_rotate_beam2inst.nc index 27a3e43e..169e3936 100644 Binary files a/examples/data/dolfyn/test_data/RDI_test01_rotate_beam2inst.nc and b/examples/data/dolfyn/test_data/RDI_test01_rotate_beam2inst.nc differ diff --git a/examples/data/dolfyn/test_data/RDI_test01_rotate_earth2principal.nc b/examples/data/dolfyn/test_data/RDI_test01_rotate_earth2principal.nc index 9b862d8a..9f1865bf 100644 Binary files a/examples/data/dolfyn/test_data/RDI_test01_rotate_earth2principal.nc and b/examples/data/dolfyn/test_data/RDI_test01_rotate_earth2principal.nc differ diff --git a/examples/data/dolfyn/test_data/RDI_test01_rotate_inst2earth.nc b/examples/data/dolfyn/test_data/RDI_test01_rotate_inst2earth.nc index 1b6aec9f..a54aa6ce 100644 Binary files a/examples/data/dolfyn/test_data/RDI_test01_rotate_inst2earth.nc and b/examples/data/dolfyn/test_data/RDI_test01_rotate_inst2earth.nc differ diff --git a/examples/data/dolfyn/test_data/RDI_withBT.dolfyn.log b/examples/data/dolfyn/test_data/RDI_withBT.dolfyn.log index 178650f3..1b06d4b8 100644 --- a/examples/data/dolfyn/test_data/RDI_withBT.dolfyn.log +++ b/examples/data/dolfyn/test_data/RDI_withBT.dolfyn.log @@ -14,12 +14,9 @@ root - INFO - id 512 offset 282 root - INFO - id 768 offset 352 root - INFO - id 1024 offset 422 root - INFO - id 1536 offset 492 -root - INFO - Done: {'prog_ver': 51.41, 'inst_make': 'TRDI', 'inst_type': 'ADCP', 'rotate_vars': ['vel'], 'has_imu': 0, 'inst_model': 'Workhorse', 'beam_angle': 20, 'freq': 600, 'beam_pattern': 'convex', 'orientation': 'down', 'n_beams': 4, 'n_cells': 17, 'pings_per_ensemble': 1, 'cell_size': 1.0, 'blank_dist': 0.88, 'profiling_mode': 1, 'min_corr_threshold': 64, 'n_code_reps': 5, 'min_prcnt_gd': 0, 'max_error_vel': 2.0, 'sec_between_ping_groups': 0.5, 'coord_sys': 'earth', 'use_pitchroll': 'yes', 'use_3beam': 'yes', 'bin_mapping': 'yes', 'heading_misalign_deg': 0.0, 'magnetic_var_deg': 0.0, 'sensors_src': '01111101', 'sensors_avail': '00111101', 'bin1_dist_m': 2.09, 'transmit_pulse_m': 1.18, 'water_ref_cells': [1, 5], 'false_target_threshold': 50, 'transmit_lag_m': 0.24, 'bandwidth': 0, 'power_level': 255, 'serialnum': 18655} +root - INFO - Done: {'firmware_ver': 51.41, 'inst_make': 'TRDI', 'inst_type': 'ADCP', 'rotate_vars': ['vel'], 'has_imu': 0, 'inst_model': 'Workhorse', 'beam_angle': 20, 'carrier_freq': 600, 'beam_pattern': 'convex', 'orientation': 'down', 'n_beams': 4, 'n_cells': 17, 'pings_per_ensemble': 1, 'cell_size': 1.0, 'blank_dist': 0.88, 'profiling_mode': 1, 'min_corr_threshold': 64, 'n_code_reps': 5, 'min_prcnt_gd': 0, 'max_error_vel': 2.0, 'sec_between_ping_groups': 0.5, 'coord_sys': 'earth', 'use_pitchroll': 'yes', 'use_3beam': 'yes', 'bin_mapping': 'yes', 'heading_misalign_deg': 0.0, 'magnetic_var_deg': 0.0, 'sensors_src': '01111101', 'sensors_avail': '00111101', 'bin1_dist_m': 2.09, 'transmit_pulse_m': 1.18, 'water_ref_cells': [1, 5], 'false_target_threshold': 50, 'transmit_lag_m': 0.24, 'bandwidth': 0, 'power_level': 255, 'serialnum': 18655} root - INFO - self._BB False root - INFO - self.cfgBB: {} -root - INFO - taking data from pings 0 - 1721 -root - INFO - 1721 ensembles will be produced. - root - INFO - 17 ncells, not BB root - DEBUG - pos 0mb/1mb @@ -99,3 +96,6 @@ root - DEBUG - pos: 865, pos_: 0, nbyte: 138, k: 0, byte_offset: -1 root - DEBUG - Trying to Read 512 root - INFO - Reading code 0x200... root - INFO - Read Corr +root - INFO - success! +root - INFO - n 4: 768 0300 +root - DEBUG - pos: 935, pos_: 0, nbyte: 70, k: 0, byte_offset: -1 diff --git a/examples/data/dolfyn/test_data/RDI_withBT.nc b/examples/data/dolfyn/test_data/RDI_withBT.nc index 4dceb180..d8452361 100644 Binary files a/examples/data/dolfyn/test_data/RDI_withBT.nc and b/examples/data/dolfyn/test_data/RDI_withBT.nc differ diff --git a/examples/data/dolfyn/test_data/RiverPro_test01.nc b/examples/data/dolfyn/test_data/RiverPro_test01.nc index 2eb6a1dd..b20dadf5 100644 Binary files a/examples/data/dolfyn/test_data/RiverPro_test01.nc and b/examples/data/dolfyn/test_data/RiverPro_test01.nc differ diff --git a/examples/data/dolfyn/test_data/dat_rdi_bt.mat b/examples/data/dolfyn/test_data/dat_rdi_bt.mat index fc14b006..52734589 100644 Binary files a/examples/data/dolfyn/test_data/dat_rdi_bt.mat and b/examples/data/dolfyn/test_data/dat_rdi_bt.mat differ diff --git a/examples/data/dolfyn/test_data/dat_vm.mat b/examples/data/dolfyn/test_data/dat_vm.mat index ceaeeb61..ea45cf77 100644 Binary files a/examples/data/dolfyn/test_data/dat_vm.mat and b/examples/data/dolfyn/test_data/dat_vm.mat differ diff --git a/examples/data/dolfyn/test_data/sentinelv_b5.nc b/examples/data/dolfyn/test_data/sentinelv_b5.nc new file mode 100644 index 00000000..8d4efd2e Binary files /dev/null and b/examples/data/dolfyn/test_data/sentinelv_b5.nc differ diff --git a/examples/data/dolfyn/test_data/vmdas01_wh.nc b/examples/data/dolfyn/test_data/vmdas01_wh.nc index 2185e144..6e5e6aff 100644 Binary files a/examples/data/dolfyn/test_data/vmdas01_wh.nc and b/examples/data/dolfyn/test_data/vmdas01_wh.nc differ diff --git a/examples/data/dolfyn/test_data/vmdas02_os.nc b/examples/data/dolfyn/test_data/vmdas02_os.nc index 9661c8e3..e3350234 100644 Binary files a/examples/data/dolfyn/test_data/vmdas02_os.nc and b/examples/data/dolfyn/test_data/vmdas02_os.nc differ diff --git a/examples/data/dolfyn/test_data/winriver01.nc b/examples/data/dolfyn/test_data/winriver01.nc index 81240296..f6a828e3 100644 Binary files a/examples/data/dolfyn/test_data/winriver01.nc and b/examples/data/dolfyn/test_data/winriver01.nc differ diff --git a/examples/data/dolfyn/test_data/winriver02.nc b/examples/data/dolfyn/test_data/winriver02.nc index 7db174ea..ad0f89a2 100644 Binary files a/examples/data/dolfyn/test_data/winriver02.nc and b/examples/data/dolfyn/test_data/winriver02.nc differ diff --git a/examples/data/dolfyn/test_data/winriver02_rotate_ship2earth.nc b/examples/data/dolfyn/test_data/winriver02_rotate_ship2earth.nc index d3767e0e..237a7ea1 100644 Binary files a/examples/data/dolfyn/test_data/winriver02_rotate_ship2earth.nc and b/examples/data/dolfyn/test_data/winriver02_rotate_ship2earth.nc differ diff --git a/examples/data/dolfyn/test_data/winriver02_transect.nc b/examples/data/dolfyn/test_data/winriver02_transect.nc index 3ae5b5ce..a00a8658 100644 Binary files a/examples/data/dolfyn/test_data/winriver02_transect.nc and b/examples/data/dolfyn/test_data/winriver02_transect.nc differ diff --git a/mhkit/dolfyn/io/base.py b/mhkit/dolfyn/io/base.py index c31f5fc0..54f29868 100644 --- a/mhkit/dolfyn/io/base.py +++ b/mhkit/dolfyn/io/base.py @@ -298,7 +298,7 @@ def _create_dataset(data): "data": data["data_vars"][key], } - elif "b5" in tg: + elif "b5" in key: ds_dict[key] = { "dims": ("range_b5", "time_b5"), "data": data["data_vars"][key], @@ -324,7 +324,7 @@ def _create_dataset(data): # "vel_b5" sometimes stored as (1, range_b5, time_b5) ds_dict[key] = { "dims": ("range_b5", "time_b5"), - "data": data["data_vars"][key][0], + "data": data["data_vars"][key].squeeze(), } elif "sl" in key: ds_dict[key] = { @@ -357,12 +357,12 @@ def _create_dataset(data): r_list = [r for r in ds.coords if "range" in r] for ky in r_list: ds[ky].attrs["units"] = "m" - ds[ky].attrs["long_name"] = "Profile Range" + ds[ky].attrs["long_name"] = "Profile " + ky.capitalize().replace("_", " ") ds[ky].attrs["description"] = "Distance to the center of each depth bin" time_list = [t for t in ds.coords if "time" in t] for ky in time_list: ds[ky].attrs["units"] = "seconds since 1970-01-01 00:00:00" - ds[ky].attrs["long_name"] = "Time" + ds[ky].attrs["long_name"] = ky.capitalize().replace("_", " ") ds[ky].attrs["standard_name"] = "time" # Set dataset metadata diff --git a/mhkit/dolfyn/io/rdi.py b/mhkit/dolfyn/io/rdi.py index 9e93a15c..530b0bac 100644 --- a/mhkit/dolfyn/io/rdi.py +++ b/mhkit/dolfyn/io/rdi.py @@ -18,9 +18,10 @@ def read_rdi( filename, userdata=None, nens=None, - debug_level=-1, + debug=0, vmdas_search=False, winriver=False, + search_num=20000, **kwargs, ) -> xr.Dataset: """ @@ -32,11 +33,11 @@ def read_rdi( Filename of TRDI file to read. userdata : True, False, or string of userdata.json filename Whether to read the '.userdata.json' file. Default = True - nens : None, int or 2-element tuple (start, stop) - Number of pings or ensembles to read from the file. + nens : None, int + Number of pings or ensembles to read from the file, starting from 0. Default is None, read entire file - debug_level : int - Debug level [0 - 2]. Default = -1 + debug : int + Debug level [0 - 3]. Default = 0 vmdas_search : bool Search from the end of each ensemble for the VMDAS navigation block. The byte offsets are sometimes incorrect. Default = False @@ -50,7 +51,7 @@ def read_rdi( An xarray dataset from the binary instrument data """ # Start debugger logging - if debug_level >= 0: + if debug > 0: for handler in logging.root.handlers[:]: logging.root.removeHandler(handler) filepath = Path(filename) @@ -65,7 +66,11 @@ def read_rdi( # Reads into a dictionary of dictionaries using netcdf naming conventions # Should be easier to debug rdr = _RDIReader( - filename, debug_level=debug_level, vmdas_search=vmdas_search, winriver=winriver + filename, + debug=debug, + vmdas_search=vmdas_search, + winriver=winriver, + search_num=search_num, ) datNB, datBB = rdr.load_data(nens=nens) @@ -123,7 +128,7 @@ def read_rdi( ) # Close handler - if debug_level >= 0: + if debug > 0: for handler in logging.root.handlers[:]: logging.root.removeHandler(handler) handler.close() @@ -159,17 +164,16 @@ def _set_rdi_declination(dat, fname, inplace): class _RDIReader: - def __init__( - self, fname, navg=1, debug_level=-1, vmdas_search=False, winriver=False - ): + def __init__(self, fname, debug, vmdas_search, winriver, search_num): self.fname = base._abspath(fname) print("\nReading file {} ...".format(fname)) - self._debug_level = debug_level + self._debug_level = debug self._vmdas_search = vmdas_search self._winrivprob = winriver self._vm_source = 0 self._pos = 0 self.progress = 0 + self.search_num = search_num self._cfac32 = np.float32(180 / 2**31) # signed 32 to float self._cfac16 = np.float32(180 / 2**15) # unsigned16 to float self._fixoffset = 0 @@ -194,11 +198,10 @@ def __init__( logging.info("self._BB {}".format(self._BB)) logging.info("self.cfgBB: {}".format(self.cfgBB)) self.f.seek(self._pos, 0) - self.n_avg = navg - self.ensemble = lib._ensemble(self.n_avg, self.cfg["n_cells"]) + self.ensemble = lib._ensemble(self.cfg["n_cells"]) if self._BB: - self.ensembleBB = lib._ensemble(self.n_avg, self.cfgBB["n_cells"]) + self.ensembleBB = lib._ensemble(self.cfgBB["n_cells"]) self.vars_read = lib._variable_setlist(["time"]) if self._BB: @@ -243,7 +246,7 @@ def read_hdrseg(self): fd = self.f hdr = self.hdr hdr["nbyte"] = fd.read_i16(1) - spare = fd.read_ui8(1) + fd.seek(1, 1) ndat = fd.read_ui8(1) hdr["dat_offsets"] = fd.read_ui16(ndat) self._nbyte = 4 + ndat * 2 @@ -278,29 +281,22 @@ def check_for_double_buffer(self): def load_data(self, nens=None): """Main function run after reader class is initiated.""" + if nens is None: - # Attempt to overshoot WinRiver2 or *Pro filesize - if (self.cfg["coord_sys"] == "ship") or ( - self.cfg["inst_model"] - in [ - "RiverPro", - "StreamPro", - ] - ): - self._nens = int(self._filesize / self.hdr["nbyte"] / self.n_avg * 1.1) - else: - # Attempt to overshoot other instrument filesizes - self._nens = int(self._npings / self.n_avg) + # Overshoot file size to pre-allocate enough ensembles + self._nens = int(self._npings * 10) elif nens.__class__ is tuple or nens.__class__ is list: raise Exception(" `nens` must be a integer") else: self._nens = nens - if self._debug_level > -1: - logging.info(" taking data from pings 0 - %d" % self._nens) - logging.info(" %d ensembles will be produced.\n" % self._nens) + + # Pre-allocate data self.init_data() - for iens in range(self._nens): + iens = 0 + while True: + if iens == self._nens: + break if not self.read_buffer(): self.remove_end(iens) break @@ -323,6 +319,9 @@ def load_data(self, nens=None): # reset flag after all variables run self.n_cells_diff = 0 + # b5 clock flag + b5 = True if "ping_offset_time_b5" in cfg else False + # Set clock clock = en.rtc[:, :] if clock[0, 0] < 100: @@ -340,8 +339,15 @@ def load_data(self, nens=None): ) ) dat["coords"]["time"][iens] = np.nan + if b5: + dat["coords"]["time_b5"][iens] = np.nan else: dat["coords"]["time"][iens] = np.median(dates) + if b5: + dat["coords"]["time_b5"][iens] = ( + np.median(dates) + cfg["ping_offset_time_b5"] + ) + iens += 1 # Finalize dataset (runs through both NB and BB) for dat, cfg in zip(datl, cfgl): @@ -402,10 +408,37 @@ def read_buffer(self): self.ensembleBB.k = -1 # so that k+=1 gives 0 on the first loop. self.print_progress() hdr = self.hdr - while self.ensemble.k < self.ensemble.n_avg - 1: + while self.ensemble.k < 0: if not self.search_buffer(): return False startpos = fd.tell() - 2 + + noBytesInEnsemble = fd.read_i16(1) + # go back to start of ensemble + fd.seek(-4, 1) + # pack the entire ensemble into a bytearray + bytesInEnsemble = bytearray(fd.read_ui8(noBytesInEnsemble)) + # get checksum (2 bytes unsigned integer) + checksum = fd.read_ui16(1) + # calculate checksum and check + # if the checksum is wrong, back up 100 bytes and search for the next + # ensemble + if (sum(bytesInEnsemble) & 0xFFFF) != checksum: + logging.warning( + "Ensemble starting at startpos {} has a checksum error".format( + startpos + ) + ) + logging.warning( + "checksum calculated = %s, actual checksum = %s\n" + % ((sum(bytesInEnsemble) & 0xFFFF), checksum) + ) + fd.seek(-100, 1) + self.read_buffer() + else: + # go back to start of ensemble + fd.seek(-noBytesInEnsemble, 1) + self.read_hdrseg() if self._debug_level > -1: logging.info("Read Header", hdr) @@ -464,7 +497,7 @@ def search_buffer(self): """ Check to see if the next bytes indicate the beginning of a data block. If not, search for the next data block, up to - _search_num times. + search_num times. """ fd = self.f id = fd.read_ui8(2) @@ -479,8 +512,11 @@ def search_buffer(self): logging.info("cfgid0: [{:x}, {:x}]".format(*cfgid)) # If not [127, 127] or if the file ends in the next ensemble while (cfgid != [127, 127]) or self.check_eof(): + if search_cnt == self.search_num: + logging.debug(f"Stopped searching at byte position {fd.tell()}") + return False + # Search for the next header or the end of the file if cfgid == [127, 121]: - # Search for the next header or the end of the file skipbytes = fd.read_i16(1) fd.seek(skipbytes - 2, 1) id = fd.read_ui8(2) @@ -497,7 +533,7 @@ def search_buffer(self): cfgid[0] = cfgid[1] cfgid[1] = nextbyte - if pos_7f79 and self._debug_level > -1: + if pos_7f79 and (self._debug_level > -1): logging.info("Skipped junk data: [{:x}, {:x}]".format(*[127, 121])) if search_cnt > 0: @@ -560,6 +596,10 @@ def read_dat(self, id): 0: (defs.read_fixed, [False]), # 0001 2nd profile fixed leader 1: (defs.read_fixed, [True]), + # 000B Wave parameters + 11: (defs.skip_Nbyte, [51]), + # 000C Wave parameters - sea and swell + 12: (defs.skip_Nbyte, [44]), # 0010 Surface layer fixed leader (RiverPro & StreamPro) 16: (defs.read_fixed_sl, []), # 0080 1st profile variable leader @@ -612,13 +652,13 @@ def read_dat(self, id): 1793: (defs.skip_Ncol, [4]), # 0701 number of pings 1794: (defs.skip_Ncol, [4]), # 0702 sum of squared vel 1795: (defs.skip_Ncol, [4]), # 0703 sum of velocities - 2560: (defs.skip_Ncol, []), # 0A00 Beam 5 velocity - 2816: (defs.skip_Ncol, []), # 0B00 Beam 5 correlation - 3072: (defs.skip_Ncol, []), # 0C00 Beam 5 amplitude - 3328: (defs.skip_Ncol, []), # 0D00 Beam 5 pct_good + 2560: (defs.read_vel_b5, []), # 0A00 Beam 5 velocity + 2816: (defs.read_corr_b5, []), # 0B00 Beam 5 correlation + 3072: (defs.read_amp_b5, []), # 0C00 Beam 5 amplitude + 3328: (defs.read_prcnt_gd_b5, []), # 0D00 Beam 5 pct_good # Fixed attitude data format for Ocean Surveyor ADCPs 3000: (defs.skip_Nbyte, [32]), - 3841: (defs.skip_Nbyte, [38]), # 0F01 Beam 5 leader + 3841: (defs.read_vel_b5_leader, []), # 0F01 Beam 5 leader 8192: (defs.read_vmdas, []), # 2000 # 2013 Navigation parameter data 8211: (defs.skip_Nbyte, [83]), @@ -648,8 +688,16 @@ def read_dat(self, id): 22785: (defs.skip_Nbyte, [65]), # 5902 Ping attitude 22786: (defs.skip_Nbyte, [105]), - # 7001 ADC data - 28673: (defs.skip_Nbyte, [14]), + # 7000 Sentinvel V system configuration + 28672: (defs.read_sentinelv_syscfg, [False]), + # 7001 Sentinel V leader + 28673: (defs.read_sentinelv_ping_setup, [False]), + # 7002 ADC data + 28674: (defs.skip_Nbyte, [14]), + # 7003 Sentinel V "Features" (only first ensemble) + 28675: (defs.skip_Nbyte, [88]), # min size + # 7004 Sentinel V Event Log + 28676: (defs.read_sentinelv_event_log, []), } # Call the correct function: if self._debug_level > 1: @@ -787,10 +835,7 @@ def save_profiles(self, dat, cfg, nm, en, iens): The updated dataset dictionary with the reformatted profile measurements. """ ds = lib._get(dat, nm) - if self.n_avg == 1: - bn = en[nm][..., 0] - else: - bn = np.nanmean(en[nm], axis=-1) + bn = en[nm][..., 0] # If n_cells has changed (RiverPro/StreamPro WinRiver transects) if len(ds.shape) == 3: @@ -873,6 +918,12 @@ def cleanup(self, dat, cfg): ).astype(np.float32) cfg["range_offset"] = round(bin1_dist - cfg["blank_dist"] - cfg["cell_size"], 3) + if "n_cells_b5" in cfg: + bin1_dist_b5 = cfg.pop("bin1_dist_b5_m") + dat["coords"]["range_b5"] = ( + bin1_dist_b5 + np.arange(cfg["n_cells_b5"]) * cfg["cell_size_b5"] + ).astype(np.float32) + # Clean up surface layer profiles if "surface_layer" in cfg: # RiverPro/StreamPro # Set SL cell size and range @@ -986,10 +1037,11 @@ def finalize(self, dat, cfg): for nm in set(defs.data_defs.keys()) - self.vars_read: lib._pop(dat, nm) - # VMDAS and WinRiver have different set sampling frequency - if ("sourceprog" in cfg) and ( - cfg["sourceprog"].lower() in ["vmdas", "winriver", "winriver2"] - ): + # Need to figure out how to differentiate burst mode from averaging mode + if ( + ("source_program" in cfg) + and (cfg["source_program"].lower() in ["vmdas", "winriver", "winriver2"]) + ) or ("sentinelv" in cfg["inst_model"].lower()): cfg["fs"] = round(1 / np.median(np.diff(dat["coords"]["time"])), 2) else: cfg["fs"] = 1 / (cfg["sec_between_ping_groups"] * cfg["pings_per_ensemble"]) @@ -997,9 +1049,10 @@ def finalize(self, dat, cfg): # Save configuration data as attributes dat["attrs"] = cfg + # Set 3D variable axes properly (beam, range, time) for nm in defs.data_defs: shp = defs.data_defs[nm][0] - if len(shp) and shp[0] == "nc" and lib._in_group(dat, nm): + if (len(shp) == 2) and (shp[0] == "nc") and lib._in_group(dat, nm): lib._setd(dat, nm, np.swapaxes(lib._get(dat, nm), 0, 1)) return dat diff --git a/mhkit/dolfyn/io/rdi_defs.py b/mhkit/dolfyn/io/rdi_defs.py index 86d66ced..936e6cc3 100644 --- a/mhkit/dolfyn/io/rdi_defs.py +++ b/mhkit/dolfyn/io/rdi_defs.py @@ -326,6 +326,47 @@ "proportion_of_acceptable_signal_returns_from_acoustic_instrument_in_sea_water", ), "status_sl": (["nc", 4], "data_vars", "float32", "1", "Surface Layer Status", ""), + "faults": ( + [], + "data_vars", + "= 8.14: + if cfg["firmware_ver"] >= 8.14: cpu_serialnum = fd.read_ui8(8) rdr._nbyte += 8 - if cfg["prog_ver"] >= 8.24: + if cfg["firmware_ver"] >= 8.24: cfg["bandwidth"] = fd.read_ui16(1) rdr._nbyte += 2 - if cfg["prog_ver"] >= 9.68: + if cfg["firmware_ver"] >= 9.68: cfg["power_level"] = fd.read_ui8(1) # cfg['navigator_basefreqindex'] = fd.read_ui8(1) fd.seek(1, 1) @@ -479,7 +519,7 @@ def read_fixed(rdr, bb=False): rdr.n_cells_diff = rdr.cfg["n_cells"] - rdr.ensemble["n_cells"] # Increase n_cells if greater than 0 if rdr.n_cells_diff > 0: - rdr.ensemble = lib._ensemble(rdr.n_avg, rdr.cfg["n_cells"]) + rdr.ensemble = lib._ensemble(rdr.cfg["n_cells"]) if rdr._debug_level > 0: logging.warning( f"Maximum number of cells increased to {rdr.cfg['n_cells']}" @@ -521,13 +561,11 @@ def read_fixed_sl(rdr): def read_var(rdr, bb=False): """Read variable header""" - fd = rdr.f if bb: ens = rdr.ensembleBB else: ens = rdr.ensemble ens.k += 1 - ens = rdr.ensemble k = ens.k rdr.vars_read += [ "number", @@ -547,6 +585,7 @@ def read_var(rdr, bb=False): "roll_std", "adc", ] + fd = rdr.f ens.number[k] = fd.read_ui16(1) ens.rtc[:, k] = fd.read_ui8(7) ens.number[k] += 65535 * fd.read_ui8(1) @@ -567,7 +606,7 @@ def read_var(rdr, bb=False): cfg = rdr.cfg if cfg["inst_model"].lower() == "broadband": - if cfg["prog_ver"] >= 5.55: + if cfg["firmware_ver"] >= 5.55: fd.seek(15, 1) cent = fd.read_ui8(1) ens.rtc[:, k] = fd.read_ui8(7) @@ -576,30 +615,30 @@ def read_var(rdr, bb=False): elif cfg["inst_model"].lower() == "ocean surveyor": fd.seek(16, 1) # 30 bytes all set to zero, 14 read above rdr._nbyte += 16 - if cfg["prog_ver"] > 23: + if cfg["firmware_ver"] > 23: fd.seek(2, 1) rdr._nbyte += 2 else: ens.error_status[k] = np.binary_repr(fd.read_ui32(1), 32) rdr.vars_read += ["pressure", "pressure_std"] rdr._nbyte += 4 - if cfg["prog_ver"] >= 8.13: + if cfg["firmware_ver"] >= 8.13: # Added pressure sensor stuff in 8.13 fd.seek(2, 1) ens.pressure[k] = fd.read_ui32(1) * 0.001 # dPa to dbar ens.pressure_std[k] = fd.read_ui32(1) * 0.001 rdr._nbyte += 10 - if cfg["prog_ver"] >= 8.24: + if cfg["firmware_ver"] >= 8.24: # Spare byte added 8.24 fd.seek(1, 1) rdr._nbyte += 1 - if cfg["prog_ver"] >= 16.05: + if cfg["firmware_ver"] >= 16.05: # Added more fields with century in clock cent = fd.read_ui8(1) ens.rtc[:, k] = fd.read_ui8(7) ens.rtc[0, k] = ens.rtc[0, k] + cent * 100 rdr._nbyte += 8 - if cfg["prog_ver"] >= 56: + if cfg["firmware_ver"] >= 56: fd.seek(1) # lag near bottom flag rdr._nbyte += 1 @@ -613,9 +652,8 @@ def read_vel(rdr, bb=0): rdr.vars_read += ["vel" + tg] n_cells = cfg["n_cells" + tg] - k = ens.k vel = np.array(rdr.f.read_i16(4 * n_cells)).reshape((n_cells, 4)) * 0.001 - ens["vel" + tg][:n_cells, :, k] = vel + ens["vel" + tg][:n_cells, :, ens.k] = vel rdr._nbyte = 2 + 4 * n_cells * 2 if rdr._debug_level > -1: logging.info("Read Vel") @@ -627,10 +665,9 @@ def read_corr(rdr, bb=0): rdr.vars_read += ["corr" + tg] n_cells = cfg["n_cells" + tg] - k = ens.k - ens["corr" + tg][:n_cells, :, k] = np.array(rdr.f.read_ui8(4 * n_cells)).reshape( - (n_cells, 4) - ) + ens["corr" + tg][:n_cells, :, ens.k] = np.array( + rdr.f.read_ui8(4 * n_cells) + ).reshape((n_cells, 4)) rdr._nbyte = 2 + 4 * n_cells if rdr._debug_level > -1: logging.info("Read Corr") @@ -642,8 +679,7 @@ def read_amp(rdr, bb=0): rdr.vars_read += ["amp" + tg] n_cells = cfg["n_cells" + tg] - k = ens.k - ens["amp" + tg][:n_cells, :, k] = np.array(rdr.f.read_ui8(4 * n_cells)).reshape( + ens["amp" + tg][:n_cells, :, ens.k] = np.array(rdr.f.read_ui8(4 * n_cells)).reshape( (n_cells, 4) ) rdr._nbyte = 2 + 4 * n_cells @@ -681,11 +717,11 @@ def read_status(rdr, bb=0): def read_bottom(rdr): """Read bottom track block""" - rdr.vars_read += ["dist_bt", "vel_bt", "corr_bt", "amp_bt", "prcnt_gd_bt"] - fd = rdr.f + cfg = rdr.cfg ens = rdr.ensemble k = ens.k - cfg = rdr.cfg + rdr.vars_read += ["dist_bt", "vel_bt", "corr_bt", "amp_bt", "prcnt_gd_bt"] + fd = rdr.f if rdr._vm_source == 2: rdr.vars_read += ["latitude_gps", "longitude_gps"] fd.seek(2, 1) @@ -724,14 +760,16 @@ def read_bottom(rdr): # Skip reference layer data fd.seek(26, 1) rdr._nbyte = 2 + 68 - if cfg["prog_ver"] >= 5.3: + if cfg["firmware_ver"] >= 5.3: fd.seek(7, 1) # skip to rangeMsb bytes ens.dist_bt[:, k] = ens.dist_bt[:, k] + fd.read_ui8(4) * 655.36 rdr._nbyte += 11 - if cfg["prog_ver"] >= 16.2 and (cfg.get("sourceprog", "").lower() != "winriver"): + if cfg["firmware_ver"] >= 16.2 and ( + cfg.get("source_program", "").lower() != "winriver" + ): fd.seek(4, 1) # not documented rdr._nbyte += 4 - if cfg["prog_ver"] >= 56.1: + if cfg["firmware_ver"] >= 56.1: fd.seek(4, 1) # not documented rdr._nbyte += 4 @@ -741,10 +779,10 @@ def read_bottom(rdr): def read_alt(rdr): """Read altimeter (range of vertical beam) block""" - fd = rdr.f ens = rdr.ensemble k = ens.k rdr.vars_read += ["alt_dist", "alt_rssi", "alt_eval", "alt_status"] + fd = rdr.f ens.alt_eval[k] = fd.read_ui8(1) # evaluation amplitude ens.alt_rssi[k] = fd.read_ui8(1) # RSSI amplitude ens.alt_dist[k] = fd.read_ui32(1) * 0.001 # range to surface/seafloor @@ -757,7 +795,7 @@ def read_alt(rdr): def read_winriver(rdr): """Skip WinRiver1 Navigation block (outdated)""" rdr._winrivprob = True - rdr.cfg["sourceprog"] = "WINRIVER" + rdr.cfg["source_program"] = "WINRIVER" if rdr._vm_source not in [2, 3]: if rdr._debug_level > -1: logging.warning( @@ -773,32 +811,33 @@ def read_winriver(rdr): def read_winriver2(rdr): """Read WinRiver2 Navigation block""" - startpos = rdr.f.tell() + fd = rdr.f + startpos = fd.tell() rdr._winrivprob = True - rdr.cfg["sourceprog"] = "WinRiver2" + rdr.cfg["source_program"] = "WinRiver2" ens = rdr.ensemble k = ens.k if rdr._debug_level > -1: logging.info("Read WinRiver2") rdr._vm_source = 3 - spid = rdr.f.read_ui16(1) # NMEA specific IDs + spid = fd.read_ui16(1) # NMEA specific IDs if spid in [4, 104]: # GGA - sz = rdr.f.read_ui16(1) - dtime = rdr.f.read_f64(1) + sz = fd.read_ui16(1) + fd.read_f64(1) # dtime if sz <= 43: # If no sentence, data is still stored in nmea format - empty_gps = rdr.f.reads(sz - 2) - rdr.f.seek(2, 1) + fd.reads(sz - 2) # empty_gps + fd.seek(2, 1) else: # TRDI rewrites the nmea string into their format if one is found - start_string = rdr.f.reads(6) + start_string = fd.reads(6) if not isinstance(start_string, str): if rdr._debug_level > 0: logging.warning( f"Invalid GGA string found in ensemble {k}," " skipping..." ) return "FAIL" - rdr.f.seek(1, 1) - gga_time = rdr.f.reads(9) + fd.seek(1, 1) + gga_time = fd.reads(9) time = tmlib.timedelta( hours=int(gga_time[0:2]), minutes=int(gga_time[2:4]), @@ -810,25 +849,25 @@ def read_winriver2(rdr): clock[0, :] += century date = tmlib.datetime(*clock[:3, 0]) + time ens.time_gps[k] = tmlib.date2epoch(date)[0] - rdr.f.seek(1, 1) - ens.latitude_gps[k] = rdr.f.read_f64(1) - tcNS = rdr.f.reads(1) # 'N' or 'S' + fd.seek(1, 1) + ens.latitude_gps[k] = fd.read_f64(1) + tcNS = fd.reads(1) # 'N' or 'S' if tcNS == "S": ens.latitude_gps[k] *= -1 - ens.longitude_gps[k] = rdr.f.read_f64(1) - tcEW = rdr.f.reads(1) # 'E' or 'W' + ens.longitude_gps[k] = fd.read_f64(1) + tcEW = fd.reads(1) # 'E' or 'W' if tcEW == "W": ens.longitude_gps[k] *= -1 - ens.fix_gps[k] = rdr.f.read_ui8(1) # gps fix type/quality - ens.n_sat_gps[k] = rdr.f.read_ui8(1) # of satellites + ens.fix_gps[k] = fd.read_ui8(1) # gps fix type/quality + ens.n_sat_gps[k] = fd.read_ui8(1) # of satellites # horizontal dilution of precision - ens.hdop_gps[k] = rdr.f.read_f32(1) - ens.elevation_gps[k] = rdr.f.read_f32(1) # altitude - m = rdr.f.reads(1) # altitude unit, 'm' - h_geoid = rdr.f.read_f32(1) # height of geoid - m2 = rdr.f.reads(1) # geoid unit, 'm' - ens.rtk_age_gps[k] = rdr.f.read_f32(1) - station_id = rdr.f.read_ui16(1) + ens.hdop_gps[k] = fd.read_f32(1) + ens.elevation_gps[k] = fd.read_f32(1) # altitude + fd.reads(1) # altitude unit, 'm' + fd.read_f32(1) # height of geoid + fd.reads(1) # geoid unit, 'm' + ens.rtk_age_gps[k] = fd.read_f32(1) + fd.read_ui16(1) # station id rdr.vars_read += [ "time_gps", "longitude_gps", @@ -839,88 +878,88 @@ def read_winriver2(rdr): "elevation_gps", "rtk_age_gps", ] - rdr._nbyte = rdr.f.tell() - startpos + 2 + rdr._nbyte = fd.tell() - startpos + 2 elif spid in [5, 105]: # VTG - sz = rdr.f.read_ui16(1) - dtime = rdr.f.read_f64(1) + sz = fd.read_ui16(1) + fd.read_f64(1) # dtime if sz <= 22: # if no data - empty_gps = rdr.f.reads(sz - 2) - rdr.f.seek(2, 1) + fd.reads(sz - 2) # empty gps + fd.seek(2, 1) else: - start_string = rdr.f.reads(6) + start_string = fd.reads(6) if not isinstance(start_string, str): if rdr._debug_level > 0: logging.warning( f"Invalid VTG string found in ensemble {k}," " skipping..." ) return "FAIL" - rdr.f.seek(1, 1) - true_track = rdr.f.read_f32(1) - t = rdr.f.reads(1) # 'T' - magn_track = rdr.f.read_f32(1) - m = rdr.f.reads(1) # 'M' - speed_knot = rdr.f.read_f32(1) - kts = rdr.f.reads(1) # 'N' - speed_kph = rdr.f.read_f32(1) - kph = rdr.f.reads(1) # 'K' - mode = rdr.f.reads(1) - # knots -> m/s + fd.seek(1, 1) + true_track = fd.read_f32(1) # track from true North + fd.reads(1) # 'T' + fd.read_f32(1) # track from magnetic North + fd.reads(1) # 'M' + speed_knot = fd.read_f32(1) # speed in knots + fd.reads(1) # 'N' + fd.read_f32(1) # speed in kph + fd.reads(1) # 'K' + fd.reads(1) # mode + # convert knots to m/s ens.speed_over_grnd_gps[k] = speed_knot / 1.944 ens.dir_over_grnd_gps[k] = true_track rdr.vars_read += ["speed_over_grnd_gps", "dir_over_grnd_gps"] - rdr._nbyte = rdr.f.tell() - startpos + 2 + rdr._nbyte = fd.tell() - startpos + 2 elif spid in [6, 106]: # 'DBT' depth sounder - sz = rdr.f.read_ui16(1) - dtime = rdr.f.read_f64(1) + sz = fd.read_ui16(1) + fd.read_f64(1) # dtime if sz <= 20: - empty_gps = rdr.f.reads(sz - 2) - rdr.f.seek(2, 1) + fd.reads(sz - 2) # empty gps + fd.seek(2, 1) else: - start_string = rdr.f.reads(6) + start_string = fd.reads(6) if not isinstance(start_string, str): if rdr._debug_level > 0: logging.warning( f"Invalid DBT string found in ensemble {k}," " skipping..." ) return "FAIL" - rdr.f.seek(1, 1) - depth_ft = rdr.f.read_f32(1) - ft = rdr.f.reads(1) # 'f' - depth_m = rdr.f.read_f32(1) - m = rdr.f.reads(1) # 'm' - depth_fathom = rdr.f.read_f32(1) - f = rdr.f.reads(1) # 'F' + fd.seek(1, 1) + fd.read_f32(1) # depth in feet + fd.reads(1) # 'f' + depth_m = fd.read_f32(1) # depth in meters + fd.reads(1) # 'm' + fd.read_f32(1) # depth in fathoms + fd.reads(1) # 'F' ens.dist_nmea[k] = depth_m rdr.vars_read += ["dist_nmea"] - rdr._nbyte = rdr.f.tell() - startpos + 2 + rdr._nbyte = fd.tell() - startpos + 2 elif spid in [7, 107]: # 'HDT' - sz = rdr.f.read_ui16(1) - dtime = rdr.f.read_f64(1) + sz = fd.read_ui16(1) + fd.read_f64(1) # dtime if sz <= 14: - empty_gps = rdr.f.reads(sz - 2) - rdr.f.seek(2, 1) + fd.reads(sz - 2) # empty gps + fd.seek(2, 1) else: - start_string = rdr.f.reads(6) + start_string = fd.reads(6) if not isinstance(start_string, str): if rdr._debug_level > 0: logging.warning( f"Invalid HDT string found in ensemble {k}," " skipping..." ) return "FAIL" - rdr.f.seek(1, 1) - ens.heading_gps[k] = rdr.f.read_f64(1) - tt = rdr.f.reads(1) + fd.seek(1, 1) + ens.heading_gps[k] = fd.read_f64(1) # gps heading + fd.reads(1) # tt rdr.vars_read += ["heading_gps"] - rdr._nbyte = rdr.f.tell() - startpos + 2 + rdr._nbyte = fd.tell() - startpos + 2 def read_vmdas(rdr): """Read VMDAS Navigation block""" fd = rdr.f - rdr.cfg["sourceprog"] = "VMDAS" + rdr.cfg["source_program"] = "VMDAS" ens = rdr.ensemble k = ens.k if rdr._vm_source != 1 and rdr._debug_level > -1: @@ -983,3 +1022,153 @@ def read_vmdas(rdr): if rdr._debug_level > -1: logging.info("Read VMDAS") rdr._read_vmdas = True + + +def read_sentinelv_syscfg(rdr, bb=False): + """Read system configuration block for Sentinel V: 0x7000""" + if bb: + cfg = rdr.cfgbb + else: + cfg = rdr.cfg + + fd = rdr.f + fw = fd.read_ui8(4) + cfg["firmware_ver"] = ".".join(fw.astype(str)) + cfg["carrier_freq"] = fd.read_ui32(1) / 1000 + cfg["pressure_rating_m"] = fd.read_ui16(1) + schema = fd.read_ui8(3) + cfg["schema"] = ".".join(schema.astype(str)) + fd.seek(1, 1) + + if rdr._debug_level > -1: + logging.info("Read Sentinel V System Configuration") + rdr._nbyte = 2 + 14 + + +def read_sentinelv_ping_setup(rdr, bb=False): + """Read 'ping setup' block for Sentinel V: 0x7001""" + if bb: + cfg = rdr.cfgbb + else: + cfg = rdr.cfg + + fd = rdr.f + fd.read_ui16(1) # ping ID + cfg["ensemble_interval"] = fd.read_ui32(1) * 0.001 + cfg["pings_per_ensemble"] = fd.read_ui16(1) + cfg["time_between_pings_s"] = fd.read_ui32(1) * 0.001 + cfg["sec_between_ping_groups"] = fd.read_ui32(1) * 0.001 + fd.seek(4, 1) + fd.read_ui16(1) # ping sequence number within ensemble + cfg["ambiguity_vel"] = fd.read_ui16(1) * 0.001 + fd.seek(4, 1) + fd.read_ui32(1) # ensemble offset + fd.read_ui16(1) # ensemble count + clock = fd.read_ui8(8) + clock[1] += century + cfg["deployment_start"] = tmlib.date2str( + tmlib.datetime(*clock[1:7], microsecond=int(float(clock[7]) * 10000)) + )[0] + if rdr._debug_level > -1: + logging.info("Read Sentinel V Ping Setup") + rdr._nbyte = 2 + 42 + + +def read_sentinelv_event_log(rdr): + """Read event log block for Sentinel V: 0x7004""" + fd = rdr.f + ens = rdr.ensemble + k = ens.k + n_faults = fd.read_ui16(1) + code = [] + if n_faults: + code.append(f"{fd.read_ui16(1)}.{fd.read_ui8(1)}.{fd.read_ui8(1)}") + rdr.vars_read += ["faults"] + ens.faults[k] = ",".join(code) + + if rdr._debug_level > -1: + logging.info("Read Sentinel V Event Log") + rdr._nbyte = 2 + 6 + 4 * (n_faults - 1) + + +def read_vel_b5_leader(rdr): + """Read Sentinel V vertical beam (b5) leader: 0x0F01""" + cfg = rdr.cfg + fd = rdr.f + rdr.vars_read += ["time_b5"] # Make sure this is added + cfg["n_cells_b5"] = fd.read_ui16(1) + fd.read_ui16(1) # n_pings_b5 + cfg["cell_size_b5"] = fd.read_ui16(1) * 0.01 + cfg["bin1_dist_b5_m"] = fd.read_ui16(1) * 0.01 + cfg["mode_b5"] = fd.read_ui16(1) + cfg["transmit_pulse_b5_m"] = fd.read_ui16(1) * 0.01 + cfg["transmit_lag_b5_m"] = fd.read_ui16(1) * 0.01 + fd.read_ui16(1) # transmit_code_elements + fd.read_ui16(1) # vertical_rssi_threshold + fd.read_ui16(1) # vertical_shallow_bin + fd.read_ui16(1) # vertical_start_bin + fd.read_ui16(1) # vertical_shallow_rssi_bin + fd.read_ui16(1) # max_core_threshold + fd.read_ui16(1) # min_core_threshold + cfg["ping_offset_time_b5"] = fd.read_ui16(1) * 0.001 + fd.seek(2, 1) + fd.read_ui16(1) # depth_screen + cfg["min_prcnt_gd_b5"] = fd.read_ui16(1) + fd.read_ui16(1) # vertical_do_proofing + + if rdr._debug_level > -1: + logging.info("Read Sentinel V Event Log") + rdr._nbyte = 2 + 38 + + +def read_vel_b5(rdr): + """Read Sentinel V vertical beam water velocity block: 0x0A00""" + ens = rdr.ensemble + cfg = rdr.cfg + rdr.vars_read += ["vel_b5"] + n_cells_b5 = cfg["n_cells_b5"] + + vel_b5 = np.array(rdr.f.read_i16(n_cells_b5)) * 0.001 + ens["vel_b5"][:n_cells_b5, ens.k] = vel_b5 + rdr._nbyte = 2 + n_cells_b5 * 2 + if rdr._debug_level > -1: + logging.info("Read Vel Beam 5") + + +def read_corr_b5(rdr): + """Read Sentinel V vertical beam acoustic signal correlation block: 0x0B00""" + ens = rdr.ensemble + cfg = rdr.cfg + rdr.vars_read += ["corr_b5"] + n_cells_b5 = cfg["n_cells_b5"] + + ens["corr_b5"][:n_cells_b5, ens.k] = np.array(rdr.f.read_ui8(n_cells_b5)) + rdr._nbyte = 2 + n_cells_b5 + if rdr._debug_level > -1: + logging.info("Read Corr Beam 5") + + +def read_amp_b5(rdr): + """Read Sentinel V vertical beam acoustic signal amplitude block: 0C00""" + ens = rdr.ensemble + cfg = rdr.cfg + rdr.vars_read += ["amp_b5"] + n_cells_b5 = cfg["n_cells_b5"] + + ens["amp_b5"][:n_cells_b5, ens.k] = np.array(rdr.f.read_ui8(n_cells_b5)) + rdr._nbyte = 2 + n_cells_b5 + if rdr._debug_level > -1: + logging.info("Read Amp Beam 5") + + +def read_prcnt_gd_b5(rdr): + """Read Sentinel V vertical beam acoustic signal 'percent good' block: 0x0D00""" + ens = rdr.ensemble + cfg = rdr.cfg + rdr.vars_read += ["prcnt_gd_b5"] + n_cells_b5 = cfg["n_cells_b5"] + + ens["prcnt_gd_b5"][:n_cells_b5, ens.k] = np.array(rdr.f.read_ui8(n_cells_b5)) + rdr._nbyte = 2 + n_cells_b5 + if rdr._debug_level > -1: + logging.info("Read PG Beam 5") diff --git a/mhkit/dolfyn/io/rdi_lib.py b/mhkit/dolfyn/io/rdi_lib.py index 03e8e2c6..897cc0c9 100644 --- a/mhkit/dolfyn/io/rdi_lib.py +++ b/mhkit/dolfyn/io/rdi_lib.py @@ -128,16 +128,13 @@ class _ensemble: def __getitem__(self, nm): return getattr(self, nm) - def __init__(self, navg, n_cells): - if navg is None or navg == 0: - navg = 1 - self.n_avg = navg + def __init__(self, n_cells): self.n_cells = n_cells for nm in data_defs: setattr( self, nm, - np.zeros(_get_size(nm, n=navg, ncell=n_cells), dtype=data_defs[nm][2]), + np.zeros(_get_size(nm, n=1, ncell=n_cells), dtype=data_defs[nm][2]), ) def clean_data(self): diff --git a/mhkit/tests/dolfyn/test_read_adp.py b/mhkit/tests/dolfyn/test_read_adp.py index 3cba999b..6cfe9000 100644 --- a/mhkit/tests/dolfyn/test_read_adp.py +++ b/mhkit/tests/dolfyn/test_read_adp.py @@ -22,6 +22,7 @@ dat_wr2 = load("winriver02.nc") dat_rp = load("RiverPro_test01.nc") dat_transect = load("winriver02_transect.nc") +dat_senb5 = load("sentinelv_b5.nc") dat_awac = load("AWAC_test01.nc") dat_awac_ud = load("AWAC_test01_ud.nc") @@ -52,6 +53,7 @@ def test_io_rdi(self): td_wr2 = read("winriver02.PD0") td_rp = read("RiverPro_test01.PD0") td_transect = read("winriver02_transect.PD0", nens=nens) + td_senb5 = read("sentinelv_b5.pd0") if make_data: save(td_rdi, "RDI_test01.nc") @@ -64,6 +66,7 @@ def test_io_rdi(self): save(td_wr2, "winriver02.nc") save(td_rp, "RiverPro_test01.nc") save(td_transect, "winriver02_transect.nc") + save(td_senb5, "sentinelv_b5.nc") return assert_allclose(td_rdi, dat_rdi, atol=1e-6) @@ -76,6 +79,7 @@ def test_io_rdi(self): assert_allclose(td_wr2, dat_wr2, atol=1e-6) assert_allclose(td_rp, dat_rp, atol=1e-6) assert_allclose(td_transect, dat_transect, atol=1e-6) + assert_allclose(td_senb5, dat_senb5, atol=1e-6) def test_io_nortek(self): nens = 100 diff --git a/mhkit/tests/dolfyn/test_read_io.py b/mhkit/tests/dolfyn/test_read_io.py index 835acc6b..54d04d5a 100644 --- a/mhkit/tests/dolfyn/test_read_io.py +++ b/mhkit/tests/dolfyn/test_read_io.py @@ -84,7 +84,7 @@ def read_file_and_test(fname): os.remove(exdt(fname)) nens = 100 - wh.read_rdi(exdt("RDI_withBT.000"), nens, debug_level=3) + wh.read_rdi(exdt("RDI_withBT.000"), nens, debug=3) awac.read_nortek(exdt("AWAC_test01.wpr"), nens, debug=True, do_checksum=True) awac.read_nortek( exdt("vector_data_imu01.VEC"), nens, debug=True, do_checksum=True