pyadps 0.1.1__py3-none-any.whl → 0.2.1b0__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.
- pyadps/Home_Page.py +5 -11
- pyadps/pages/01_Read_File.py +19 -188
- pyadps/pages/02_View_Raw_Data.py +33 -69
- pyadps/pages/03_Download_Raw_File.py +61 -149
- pyadps/pages/04_QC_Test.py +334 -0
- pyadps/pages/05_Profile_Test.py +575 -0
- pyadps/pages/06_Velocity_Test.py +341 -0
- pyadps/pages/07_Write_File.py +452 -0
- pyadps/utils/__init__.py +3 -3
- pyadps/utils/autoprocess.py +78 -344
- pyadps/utils/cutbin.py +413 -0
- pyadps/utils/metadata/config.ini +4 -22
- pyadps/utils/plotgen.py +3 -505
- pyadps/utils/profile_test.py +125 -494
- pyadps/utils/pyreadrdi.py +17 -27
- pyadps/utils/readrdi.py +18 -164
- pyadps/utils/{__pycache__/regrid.cpython-312.pyc → regrid.py} +0 -0
- pyadps/utils/script.py +147 -197
- pyadps/utils/signal_quality.py +24 -344
- pyadps/utils/velocity_test.py +31 -79
- pyadps/utils/writenc.py +21 -155
- {pyadps-0.1.1.dist-info → pyadps-0.2.1b0.dist-info}/METADATA +5 -5
- pyadps-0.2.1b0.dist-info/RECORD +31 -0
- {pyadps-0.1.1.dist-info → pyadps-0.2.1b0.dist-info}/WHEEL +1 -1
- {pyadps-0.1.1.dist-info → pyadps-0.2.1b0.dist-info}/entry_points.txt +0 -1
- pyadps/pages/04_Sensor_Health.py +0 -905
- pyadps/pages/05_QC_Test.py +0 -476
- pyadps/pages/06_Profile_Test.py +0 -971
- pyadps/pages/07_Velocity_Test.py +0 -600
- pyadps/pages/08_Write_File.py +0 -587
- pyadps/pages/09_Auto_process.py +0 -64
- pyadps/pages/__pycache__/__init__.cpython-312.pyc +0 -0
- pyadps/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- pyadps/utils/__pycache__/autoprocess.cpython-312.pyc +0 -0
- pyadps/utils/__pycache__/cutbin.cpython-312.pyc +0 -0
- pyadps/utils/__pycache__/plotgen.cpython-312.pyc +0 -0
- pyadps/utils/__pycache__/profile_test.cpython-312.pyc +0 -0
- pyadps/utils/__pycache__/pyreadrdi.cpython-312.pyc +0 -0
- pyadps/utils/__pycache__/readrdi.cpython-312.pyc +0 -0
- pyadps/utils/__pycache__/script.cpython-312.pyc +0 -0
- pyadps/utils/__pycache__/sensor_health.cpython-312.pyc +0 -0
- pyadps/utils/__pycache__/signal_quality.cpython-312.pyc +0 -0
- pyadps/utils/__pycache__/velocity_test.cpython-312.pyc +0 -0
- pyadps/utils/__pycache__/writenc.cpython-312.pyc +0 -0
- pyadps/utils/metadata/demo.000 +0 -0
- pyadps/utils/sensor_health.py +0 -120
- pyadps-0.1.1.dist-info/RECORD +0 -47
- {pyadps-0.1.1.dist-info → pyadps-0.2.1b0.dist-info}/LICENSE +0 -0
pyadps/utils/pyreadrdi.py
CHANGED
@@ -320,7 +320,7 @@ def safe_read(bfile, num_bytes):
|
|
320
320
|
|
321
321
|
if len(readbytes) != num_bytes:
|
322
322
|
print(f"Unexpected end of file: fewer than {num_bytes} bytes were read.")
|
323
|
-
return (
|
323
|
+
return (readbytes, ErrorCode.FILE_CORRUPTED)
|
324
324
|
else:
|
325
325
|
return (readbytes, ErrorCode.SUCCESS)
|
326
326
|
|
@@ -427,7 +427,6 @@ def fileheader(rdi_file):
|
|
427
427
|
error = ErrorCode.WRONG_RDIFILE_TYPE
|
428
428
|
print(bcolors.FAIL + error.message + bcolors.ENDC)
|
429
429
|
error_code = error.code
|
430
|
-
dummytuple = ([], [], [], [], [], ensemble, error_code)
|
431
430
|
return dummytuple
|
432
431
|
else:
|
433
432
|
if headerid[i] != 127 or sourceid[i] != 127:
|
@@ -443,14 +442,8 @@ def fileheader(rdi_file):
|
|
443
442
|
print(f"Ensembles reset to {i}" + bcolors.ENDC)
|
444
443
|
break
|
445
444
|
|
446
|
-
|
447
|
-
|
448
|
-
address_offset.append(data)
|
449
|
-
except:
|
450
|
-
error = ErrorCode.FILE_CORRUPTED
|
451
|
-
error_code = error.code
|
452
|
-
dummytuple = ([], [], [], [], [], ensemble, error_code)
|
453
|
-
return dummytuple
|
445
|
+
data = unpack("H" * datatype[i], dbyte)
|
446
|
+
address_offset.append(data)
|
454
447
|
|
455
448
|
skip_array = [None] * datatype[i]
|
456
449
|
for dtype in range(datatype[i]):
|
@@ -560,7 +553,7 @@ def fixedleader(rdi_file, byteskip=None, offset=None, idarray=None, ensemble=0):
|
|
560
553
|
fbyteskip = None
|
561
554
|
for count, item in enumerate(idarray[i]):
|
562
555
|
if item in (0, 1):
|
563
|
-
fbyteskip = offset[
|
556
|
+
fbyteskip = offset[1][count]
|
564
557
|
if fbyteskip == None:
|
565
558
|
error = ErrorCode.ID_NOT_FOUND
|
566
559
|
ensemble = i
|
@@ -710,7 +703,7 @@ def variableleader(rdi_file, byteskip=None, offset=None, idarray=None, ensemble=
|
|
710
703
|
fbyteskip = None
|
711
704
|
for count, item in enumerate(idarray[i]):
|
712
705
|
if item in (128, 129):
|
713
|
-
fbyteskip = offset[
|
706
|
+
fbyteskip = offset[1][count]
|
714
707
|
if fbyteskip == None:
|
715
708
|
error = ErrorCode.ID_NOT_FOUND
|
716
709
|
ensemble = i
|
@@ -890,7 +883,7 @@ def datatype(
|
|
890
883
|
|
891
884
|
# These arguments are outputs of fixedleader function.
|
892
885
|
# Makes the code faster if the fixedheader function is already executed.
|
893
|
-
if
|
886
|
+
if cell == 0 or beam == 0:
|
894
887
|
flead, ensemble, fl_error_code = fixedleader(
|
895
888
|
filename,
|
896
889
|
byteskip=byteskip,
|
@@ -898,23 +891,22 @@ def datatype(
|
|
898
891
|
idarray=idarray,
|
899
892
|
ensemble=ensemble,
|
900
893
|
)
|
901
|
-
cell = []
|
902
|
-
beam = []
|
903
|
-
cell = flead[7][:]
|
904
|
-
beam = flead[6][:]
|
894
|
+
cell = int(flead[7][0])
|
895
|
+
beam = int(flead[6][0])
|
905
896
|
if fl_error_code != 0:
|
906
897
|
error_code = fl_error_code
|
907
898
|
else:
|
908
|
-
cell = cell
|
909
|
-
beam = beam
|
899
|
+
cell = int(cell)
|
900
|
+
beam = int(beam)
|
901
|
+
|
910
902
|
# Velocity is 16 bits and all others are 8 bits.
|
911
903
|
# Create empty array for the chosen variable name.
|
912
904
|
if var_name == "velocity":
|
913
|
-
var_array = np.
|
905
|
+
var_array = np.zeros((beam, cell, ensemble), dtype="int16")
|
914
906
|
bitstr = "<h"
|
915
907
|
bitint = 2
|
916
908
|
else: # inserted
|
917
|
-
var_array = np.zeros((
|
909
|
+
var_array = np.zeros((beam, cell, ensemble), dtype="uint8")
|
918
910
|
bitstr = "<B"
|
919
911
|
bitint = 1
|
920
912
|
# -----------------------------
|
@@ -943,9 +935,7 @@ def datatype(
|
|
943
935
|
fbyteskip = None
|
944
936
|
for count, item in enumerate(idarray[0][:]):
|
945
937
|
if item in vid:
|
946
|
-
fbyteskip = []
|
947
|
-
for i in range(ensemble):
|
948
|
-
fbyteskip.append(int(offset[i][count]))
|
938
|
+
fbyteskip = offset[1][count]
|
949
939
|
break
|
950
940
|
if fbyteskip is None:
|
951
941
|
print(
|
@@ -958,10 +948,10 @@ def datatype(
|
|
958
948
|
|
959
949
|
# READ DATA
|
960
950
|
for i in range(ensemble):
|
961
|
-
bfile.seek(fbyteskip
|
951
|
+
bfile.seek(fbyteskip, 1)
|
962
952
|
bdata = bfile.read(2)
|
963
|
-
for cno in range(
|
964
|
-
for bno in range(
|
953
|
+
for cno in range(cell):
|
954
|
+
for bno in range(beam):
|
965
955
|
bdata = bfile.read(bitint)
|
966
956
|
varunpack = unpack(bitstr, bdata)
|
967
957
|
var_array[bno][cno][i] = varunpack[0]
|
pyadps/utils/readrdi.py
CHANGED
@@ -3,9 +3,9 @@
|
|
3
3
|
"""
|
4
4
|
RDI ADCP Binary File Reader
|
5
5
|
===========================
|
6
|
-
This module provides classes and functions to read and extract data from RDI Acoustic Doppler
|
7
|
-
Current Profiler (ADCP) binary files. The module supports Workhorse, Ocean Surveyor, and DVS ADCPs.
|
8
|
-
It allows for parsing of various data types such as Fixed Leader, Variable Leader, Velocity, Correlation,
|
6
|
+
This module provides classes and functions to read and extract data from RDI Acoustic Doppler
|
7
|
+
Current Profiler (ADCP) binary files. The module supports Workhorse, Ocean Surveyor, and DVS ADCPs.
|
8
|
+
It allows for parsing of various data types such as Fixed Leader, Variable Leader, Velocity, Correlation,
|
9
9
|
Echo Intensity, Percent Good, and Status data.
|
10
10
|
|
11
11
|
Classes
|
@@ -28,7 +28,7 @@ Status
|
|
28
28
|
Parses the status data from the ADCP.
|
29
29
|
ReadFile
|
30
30
|
Manages the entire data extraction process and unifies all data types.
|
31
|
-
|
31
|
+
|
32
32
|
Functions
|
33
33
|
---------
|
34
34
|
check_equal(array)
|
@@ -101,7 +101,6 @@ import os
|
|
101
101
|
import sys
|
102
102
|
|
103
103
|
import numpy as np
|
104
|
-
import pandas as pd
|
105
104
|
from pyadps.utils import pyreadrdi
|
106
105
|
|
107
106
|
|
@@ -130,7 +129,9 @@ class DotDict:
|
|
130
129
|
# with open(json_file_path, "r") as file:
|
131
130
|
# dictionary = json.load(file)
|
132
131
|
else:
|
133
|
-
dictionary =
|
132
|
+
dictionary = (
|
133
|
+
{}
|
134
|
+
) # Initialize an empty dictionary if no JSON file is found
|
134
135
|
self._initialize_from_dict(dictionary)
|
135
136
|
|
136
137
|
def _initialize_from_dict(self, dictionary):
|
@@ -434,7 +435,7 @@ def flead_dict(fid, dim=2):
|
|
434
435
|
"False Target Thresh": "int64",
|
435
436
|
"Spare 1": "int64",
|
436
437
|
"Transmit Lag Dist": "int64",
|
437
|
-
"CPU Serial No": "
|
438
|
+
"CPU Serial No": "int64",
|
438
439
|
"System Bandwidth": "int64",
|
439
440
|
"System Power": "int64",
|
440
441
|
"Spare 2": "int64",
|
@@ -446,15 +447,9 @@ def flead_dict(fid, dim=2):
|
|
446
447
|
counter = 1
|
447
448
|
for key, value in fname.items():
|
448
449
|
if dim == 2:
|
449
|
-
|
450
|
-
flead[key] = np.uint64(fid[:][counter])
|
451
|
-
else:
|
452
|
-
flead[key] = np.int64(fid[:][counter])
|
450
|
+
flead[key] = getattr(np, value)(fid[:][counter])
|
453
451
|
elif dim == 1:
|
454
|
-
|
455
|
-
flead[key] = np.uint64(fid[counter])
|
456
|
-
else:
|
457
|
-
flead[key] = np.int64(fid[counter])
|
452
|
+
flead[key] = getattr(np, value)(fid[counter])
|
458
453
|
else:
|
459
454
|
print("ERROR: Higher dimensions not allowed")
|
460
455
|
sys.exit()
|
@@ -510,7 +505,6 @@ class FixedLeader:
|
|
510
505
|
)
|
511
506
|
self.warning = pyreadrdi.ErrorCode.get_message(self.error)
|
512
507
|
|
513
|
-
self.data = np.uint64(self.data)
|
514
508
|
self.fleader = flead_dict(self.data)
|
515
509
|
self._initialize_from_dict(DotDict(json_file_path="flmeta.json"))
|
516
510
|
|
@@ -884,7 +878,7 @@ class VariableLeader:
|
|
884
878
|
setattr(getattr(self, key), "data", self.data[i])
|
885
879
|
i = i + 1
|
886
880
|
|
887
|
-
def
|
881
|
+
def bit_result(self):
|
888
882
|
"""
|
889
883
|
Extracts Bit Results from Variable Leader (Byte 13 & 14)
|
890
884
|
This field is part of the WorkHorse ADCP’s Built-in Test function.
|
@@ -963,6 +957,8 @@ class VariableLeader:
|
|
963
957
|
|
964
958
|
scale_factor = scale_list.get(fixclass["Frequency"])
|
965
959
|
|
960
|
+
print(fixclass["Frequency"])
|
961
|
+
|
966
962
|
channel["Xmit Voltage"] = adc1 * (scale_factor[0] / 1000000)
|
967
963
|
|
968
964
|
channel["Xmit Current"] = adc0 * (scale_factor[1] / 1000000)
|
@@ -979,80 +975,6 @@ class VariableLeader:
|
|
979
975
|
|
980
976
|
return channel
|
981
977
|
|
982
|
-
def error_status_word(self, esw=1):
|
983
|
-
bitset1 = (
|
984
|
-
"Bus Error exception",
|
985
|
-
"Address Error exception",
|
986
|
-
"Zero Divide exception",
|
987
|
-
"Emulator exception",
|
988
|
-
"Unassigned exception",
|
989
|
-
"Watchdog restart occurred",
|
990
|
-
"Batter Saver Power",
|
991
|
-
)
|
992
|
-
|
993
|
-
bitset2 = (
|
994
|
-
"Pinging",
|
995
|
-
"Not Used 1",
|
996
|
-
"Not Used 2",
|
997
|
-
"Not Used 3",
|
998
|
-
"Not Used 4",
|
999
|
-
"Not Used 5",
|
1000
|
-
"Cold Wakeup occured",
|
1001
|
-
"Unknown Wakeup occured",
|
1002
|
-
)
|
1003
|
-
|
1004
|
-
bitset3 = (
|
1005
|
-
"Clock Read error occured",
|
1006
|
-
"Unexpected alarm",
|
1007
|
-
"Clock jump forward",
|
1008
|
-
"Clock jump backward",
|
1009
|
-
"Not Used 6",
|
1010
|
-
"Not Used 7",
|
1011
|
-
"Not Used 8",
|
1012
|
-
"Not Used 9",
|
1013
|
-
)
|
1014
|
-
|
1015
|
-
bitset4 = (
|
1016
|
-
"Not Used 10",
|
1017
|
-
"Not Used 11",
|
1018
|
-
"Not Used 12",
|
1019
|
-
"Power Fail Unrecorded",
|
1020
|
-
"Spurious level 4 intr DSP",
|
1021
|
-
"Spurious level 5 intr UART",
|
1022
|
-
"Spurious level 6 intr CLOCK",
|
1023
|
-
"Level 7 interrup occured",
|
1024
|
-
)
|
1025
|
-
|
1026
|
-
if esw == 1:
|
1027
|
-
bitset = bitset1
|
1028
|
-
errorarray = self.vleader["Error Status Word 1"]
|
1029
|
-
elif esw == 2:
|
1030
|
-
bitset = bitset2
|
1031
|
-
errorarray = self.vleader["Error Status Word 2"]
|
1032
|
-
elif esw == 3:
|
1033
|
-
bitset = bitset3
|
1034
|
-
errorarray = self.vleader["Error Status Word 3"]
|
1035
|
-
else:
|
1036
|
-
bitset = bitset4
|
1037
|
-
errorarray = self.vleader["Error Status Word 4"]
|
1038
|
-
|
1039
|
-
errorstatus = dict()
|
1040
|
-
# bitarray = np.zeros(32, dtype='str')
|
1041
|
-
|
1042
|
-
for item in bitset:
|
1043
|
-
errorstatus[item] = np.array([])
|
1044
|
-
|
1045
|
-
for data in errorarray:
|
1046
|
-
byte_split = format(data, "08b")
|
1047
|
-
bitposition = 0
|
1048
|
-
for item in bitset:
|
1049
|
-
errorstatus[item] = np.append(
|
1050
|
-
errorstatus[item], byte_split[bitposition]
|
1051
|
-
)
|
1052
|
-
bitposition += 1
|
1053
|
-
|
1054
|
-
return errorstatus
|
1055
|
-
|
1056
978
|
|
1057
979
|
class Velocity:
|
1058
980
|
"""
|
@@ -1106,7 +1028,7 @@ class Velocity:
|
|
1106
1028
|
self.cells = cell
|
1107
1029
|
self.beams = beam
|
1108
1030
|
|
1109
|
-
self.
|
1031
|
+
self.units = "mm/s"
|
1110
1032
|
self.missing_value = "-32768"
|
1111
1033
|
self.scale_factor = 1
|
1112
1034
|
self.valid_min = -32768
|
@@ -1165,7 +1087,7 @@ class Correlation:
|
|
1165
1087
|
self.cells = cell
|
1166
1088
|
self.beams = beam
|
1167
1089
|
|
1168
|
-
self.
|
1090
|
+
self.units = ""
|
1169
1091
|
self.scale_factor = 1
|
1170
1092
|
self.valid_min = 0
|
1171
1093
|
self.valid_max = 255
|
@@ -1224,7 +1146,7 @@ class Echo:
|
|
1224
1146
|
self.cells = cell
|
1225
1147
|
self.beams = beam
|
1226
1148
|
|
1227
|
-
self.
|
1149
|
+
self.units = "counts"
|
1228
1150
|
self.scale_factor = "0.45"
|
1229
1151
|
self.valid_min = 0
|
1230
1152
|
self.valid_max = 255
|
@@ -1283,7 +1205,7 @@ class PercentGood:
|
|
1283
1205
|
self.cells = cell
|
1284
1206
|
self.beams = beam
|
1285
1207
|
|
1286
|
-
self.
|
1208
|
+
self.units = "percent"
|
1287
1209
|
self.valid_min = 0
|
1288
1210
|
self.valid_max = 100
|
1289
1211
|
self.long_name = "Percent Good"
|
@@ -1341,7 +1263,7 @@ class Status:
|
|
1341
1263
|
self.cells = cell
|
1342
1264
|
self.beams = beam
|
1343
1265
|
|
1344
|
-
self.
|
1266
|
+
self.units = ""
|
1345
1267
|
self.valid_min = 0
|
1346
1268
|
self.valid_max = 1
|
1347
1269
|
self.long_name = "Status Data Format"
|
@@ -1469,47 +1391,6 @@ class ReadFile:
|
|
1469
1391
|
warning_array["Status"] = self.status.warning
|
1470
1392
|
ensemble_array["Status"] = self.status.ensembles
|
1471
1393
|
|
1472
|
-
# Add Time Axis
|
1473
|
-
year = self.variableleader.vleader["RTC Year"]
|
1474
|
-
month = self.variableleader.vleader["RTC Month"]
|
1475
|
-
day = self.variableleader.vleader["RTC Day"]
|
1476
|
-
hour = self.variableleader.vleader["RTC Hour"]
|
1477
|
-
minute = self.variableleader.vleader["RTC Minute"]
|
1478
|
-
second = self.variableleader.vleader["RTC Second"]
|
1479
|
-
year = year + 2000
|
1480
|
-
date_df = pd.DataFrame(
|
1481
|
-
{
|
1482
|
-
"year": year,
|
1483
|
-
"month": month,
|
1484
|
-
"day": day,
|
1485
|
-
"hour": hour,
|
1486
|
-
"minute": minute,
|
1487
|
-
"second": second,
|
1488
|
-
}
|
1489
|
-
)
|
1490
|
-
self.time = pd.to_datetime(date_df)
|
1491
|
-
|
1492
|
-
# Depth
|
1493
|
-
# Create a depth axis with mean depth in 'm'
|
1494
|
-
cell1 = self.fixedleader.field()["Cells"]
|
1495
|
-
bin1dist1 = self.fixedleader.field()["Bin 1 Dist"] / 100
|
1496
|
-
depth_cell_len1 = self.fixedleader.field()["Depth Cell Len"] / 100
|
1497
|
-
beam_direction1 = self.fixedleader.system_configuration()["Beam Direction"]
|
1498
|
-
mean_depth = np.mean(self.variableleader.vleader["Depth of Transducer"]) / 10
|
1499
|
-
mean_depth = np.trunc(mean_depth)
|
1500
|
-
if beam_direction1.lower() == "up":
|
1501
|
-
sgn = -1
|
1502
|
-
else:
|
1503
|
-
sgn = 1
|
1504
|
-
first_depth = mean_depth + sgn * bin1dist1
|
1505
|
-
last_depth = first_depth + sgn * cell1 * depth_cell_len1
|
1506
|
-
z = np.arange(first_depth, last_depth, sgn * depth_cell_len1)
|
1507
|
-
self.depth = z
|
1508
|
-
|
1509
|
-
# Add all attributes/method/data from FixedLeader and VariableLeader
|
1510
|
-
self._copy_attributes_from_var()
|
1511
|
-
|
1512
|
-
# Error Codes and Warnings
|
1513
1394
|
self.error_codes = error_array
|
1514
1395
|
self.warnings = warning_array
|
1515
1396
|
self.ensemble_array = ensemble_array
|
@@ -1525,33 +1406,6 @@ class ReadFile:
|
|
1525
1406
|
else:
|
1526
1407
|
self.isWarning = True
|
1527
1408
|
|
1528
|
-
# Add additional attributes
|
1529
|
-
# Ensemble
|
1530
|
-
dtens = self.ensemble_value_array
|
1531
|
-
minens = np.min(dtens)
|
1532
|
-
self.ensembles = minens
|
1533
|
-
|
1534
|
-
# Add attribute that lists all variables/functions
|
1535
|
-
self.list_vars = list(vars(self).keys())
|
1536
|
-
|
1537
|
-
def _copy_attributes_from_var(self):
|
1538
|
-
for attr_name, attr_value in self.variableleader.__dict__.items():
|
1539
|
-
# Copy each attribute of var into self
|
1540
|
-
setattr(self, attr_name, attr_value)
|
1541
|
-
for attr_name, attr_value in self.fixedleader.__dict__.items():
|
1542
|
-
# Copy each attribute of var into self
|
1543
|
-
setattr(self, attr_name, attr_value)
|
1544
|
-
|
1545
|
-
def __getattr__(self, name):
|
1546
|
-
# Delegate attribute/method access to self.var if not found in self
|
1547
|
-
if hasattr(self.variableleader, name):
|
1548
|
-
return getattr(self.variableleader, name)
|
1549
|
-
if hasattr(self.fixedleader, name):
|
1550
|
-
return getattr(self.fixedleader, name)
|
1551
|
-
raise AttributeError(
|
1552
|
-
f"'{self.__class__.__name__}' object has no attribute '{name}'"
|
1553
|
-
)
|
1554
|
-
|
1555
1409
|
def fixensemble(self, min_cutoff=0):
|
1556
1410
|
"""
|
1557
1411
|
Fixes the ensemble size across all data types in the file if they differ.
|
Binary file
|