pyadps 0.1.1__py3-none-any.whl → 0.2.0b0__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.
Files changed (48) hide show
  1. pyadps/Home_Page.py +5 -11
  2. pyadps/pages/01_Read_File.py +17 -190
  3. pyadps/pages/02_View_Raw_Data.py +33 -69
  4. pyadps/pages/03_Download_Raw_File.py +61 -149
  5. pyadps/pages/04_QC_Test.py +334 -0
  6. pyadps/pages/05_Profile_Test.py +575 -0
  7. pyadps/pages/06_Velocity_Test.py +341 -0
  8. pyadps/pages/07_Write_File.py +452 -0
  9. pyadps/utils/__init__.py +3 -3
  10. pyadps/utils/autoprocess.py +78 -344
  11. pyadps/utils/cutbin.py +413 -0
  12. pyadps/utils/metadata/config.ini +4 -22
  13. pyadps/utils/plotgen.py +3 -505
  14. pyadps/utils/profile_test.py +125 -494
  15. pyadps/utils/pyreadrdi.py +17 -27
  16. pyadps/utils/readrdi.py +18 -164
  17. pyadps/utils/{__pycache__/regrid.cpython-312.pyc → regrid.py} +0 -0
  18. pyadps/utils/script.py +147 -197
  19. pyadps/utils/signal_quality.py +24 -344
  20. pyadps/utils/velocity_test.py +31 -79
  21. pyadps/utils/writenc.py +21 -155
  22. {pyadps-0.1.1.dist-info → pyadps-0.2.0b0.dist-info}/METADATA +24 -55
  23. pyadps-0.2.0b0.dist-info/RECORD +31 -0
  24. {pyadps-0.1.1.dist-info → pyadps-0.2.0b0.dist-info}/WHEEL +1 -1
  25. {pyadps-0.1.1.dist-info → pyadps-0.2.0b0.dist-info}/entry_points.txt +0 -1
  26. pyadps/pages/04_Sensor_Health.py +0 -905
  27. pyadps/pages/05_QC_Test.py +0 -476
  28. pyadps/pages/06_Profile_Test.py +0 -971
  29. pyadps/pages/07_Velocity_Test.py +0 -600
  30. pyadps/pages/08_Write_File.py +0 -587
  31. pyadps/pages/09_Auto_process.py +0 -64
  32. pyadps/pages/__pycache__/__init__.cpython-312.pyc +0 -0
  33. pyadps/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  34. pyadps/utils/__pycache__/autoprocess.cpython-312.pyc +0 -0
  35. pyadps/utils/__pycache__/cutbin.cpython-312.pyc +0 -0
  36. pyadps/utils/__pycache__/plotgen.cpython-312.pyc +0 -0
  37. pyadps/utils/__pycache__/profile_test.cpython-312.pyc +0 -0
  38. pyadps/utils/__pycache__/pyreadrdi.cpython-312.pyc +0 -0
  39. pyadps/utils/__pycache__/readrdi.cpython-312.pyc +0 -0
  40. pyadps/utils/__pycache__/script.cpython-312.pyc +0 -0
  41. pyadps/utils/__pycache__/sensor_health.cpython-312.pyc +0 -0
  42. pyadps/utils/__pycache__/signal_quality.cpython-312.pyc +0 -0
  43. pyadps/utils/__pycache__/velocity_test.cpython-312.pyc +0 -0
  44. pyadps/utils/__pycache__/writenc.cpython-312.pyc +0 -0
  45. pyadps/utils/metadata/demo.000 +0 -0
  46. pyadps/utils/sensor_health.py +0 -120
  47. pyadps-0.1.1.dist-info/RECORD +0 -47
  48. {pyadps-0.1.1.dist-info → pyadps-0.2.0b0.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 (None, ErrorCode.FILE_CORRUPTED)
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
- try:
447
- data = unpack("H" * datatype[i], dbyte)
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[0][count]
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[0][count]
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 isinstance(cell, (np.integer, int)) or isinstance(beam, (np.integer, int)):
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.full((int(max(beam)), int(max(cell)), ensemble), -32768, dtype="int16")
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((int(max(beam)), int(max(cell)), ensemble), dtype="uint8")
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[i], 1)
951
+ bfile.seek(fbyteskip, 1)
962
952
  bdata = bfile.read(2)
963
- for cno in range(int(cell[i])):
964
- for bno in range(int(beam[i])):
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 = {} # Initialize an empty dictionary if no JSON file is found
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": "int128",
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
- if key == "CPU Serial No":
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
- if key == "CPU Serial No":
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 bitresult(self):
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.unit = "mm/s"
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.unit = ""
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.unit = "counts"
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.unit = "percent"
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.unit = ""
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.