pyadps 0.1.0b0__py3-none-any.whl → 0.1.2__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 CHANGED
@@ -8,16 +8,22 @@ def main():
8
8
  layout="wide",
9
9
  initial_sidebar_state="auto",
10
10
  menu_items={
11
- "Get Help": "http://github.com/p-amol/adps",
12
- "Report a bug": "http://github.com/adps/issues",
11
+ "Get Help": "https://github.com/p-amol/pyadps",
12
+ "Report a bug": "https://github.com/p-amol/pyadps/issues",
13
13
  "About": "# Python ADCP Data Processing Software (PyADPS)",
14
14
  },
15
15
  )
16
16
 
17
17
  """
18
18
  # **Python ADCP Data Processing Software (pyadps)**
19
- `pyadps` is a software for processing Teledyne RDI Acoustic Doppler Current Profiler (ADCP) PD0 files. Currently the software can process the data from Workhorse ADCPs.
19
+
20
+ `pyadps` is a Python package for processing moored Acoustic Doppler Current Profiler (ADCP) data. It provides various functionalities such as data reading, quality control tests, NetCDF file creation, and visualization.
20
21
 
22
+ This software offers both a graphical interface (Streamlit) for those new to Python and direct Python package access for experienced users. Please note that pyadps is primarily designed for Teledyne RDI workhorse ADCPs. Other company's ADCP files are not compatible, and while some other RDI models may work, they might require additional considerations.
23
+
24
+ * Documentation: https://pyadps.readthedocs.io
25
+ * Source code: https://github.com/p-amol/pyadps
26
+ * Bug reports: https://github.com/p-amol/pyadps/issues
21
27
  ## Features
22
28
 
23
29
  * Access RDI ADCP binary files using Python 3
@@ -25,8 +31,8 @@ def main():
25
31
  * Process ADCP data
26
32
 
27
33
  ## Contribute
28
- Issue Tracker: http://github.com/adps/issues
29
- Source Code: http://github.com/p-amol/adps
34
+ Issue Tracker: https://github.com/p-amol/pyadps/issues
35
+ Source Code: https://github.com/p-amol/pyadps
30
36
 
31
37
  ## Support
32
38
  If you are having issues, please let us know.
@@ -1,12 +1,15 @@
1
1
  import os
2
2
  import tempfile
3
3
 
4
+ import numpy as np
4
5
  import pandas as pd
5
6
  import streamlit as st
6
7
  import utils.readrdi as rd
7
- import utils.writenc as wr
8
- from streamlit.runtime.state import session_state
9
8
  from utils.signal_quality import default_mask
9
+ from utils.readrdi import ReadFile
10
+
11
+ # To make the page wider if the user presses the reload button.
12
+ st.set_page_config(layout="wide")
10
13
 
11
14
  """
12
15
  Streamlit page to load ADCP binary file and display File Header
@@ -17,10 +20,10 @@ if "fname" not in st.session_state:
17
20
  st.session_state.fname = "No file selected"
18
21
 
19
22
  if "rawfilename" not in st.session_state:
20
- st.session_state.rawfilename = "rawfile.nc"
23
+ st.session_state.rawfilename = "RAW_DAT.nc"
21
24
 
22
25
  if "vleadfilename" not in st.session_state:
23
- st.session_state.vleadfilename = "vlead.nc"
26
+ st.session_state.vleadfilename = "RAW_VAR.nc"
24
27
 
25
28
 
26
29
  ################ Functions #######################
@@ -110,6 +113,7 @@ if uploaded_file is not None:
110
113
  correlation = ds.correlation.data
111
114
  echo = ds.echo.data
112
115
  pgood = ds.percentgood.data
116
+ beamdir = ds.fixedleader.system_configuration()["Beam Direction"]
113
117
 
114
118
  st.session_state.fname = uploaded_file.name
115
119
  st.session_state.head = ds.fileheader
@@ -119,6 +123,16 @@ if uploaded_file is not None:
119
123
  st.session_state.echo = ds.echo.data
120
124
  st.session_state.correlation = ds.correlation.data
121
125
  st.session_state.pgood = ds.percentgood.data
126
+ st.session_state.beam_direction = beamdir
127
+ st.session_state.sound_speed = ds.variableleader.speed_of_sound.data
128
+ st.session_state.depth = ds.variableleader.depth_of_transducer.data
129
+ st.session_state.temperature = (
130
+ ds.variableleader.temperature.data * ds.variableleader.temperature.scale
131
+ )
132
+ st.session_state.salinity = (
133
+ ds.variableleader.salinity.data * ds.variableleader.salinity.scale
134
+ )
135
+ st.session_state.filename = (ds.filename)
122
136
 
123
137
  # st.session_state.flead = flead
124
138
  # st.session_state.vlead = vlead
@@ -132,6 +146,9 @@ if uploaded_file is not None:
132
146
  elif "flead" in st.session_state:
133
147
  st.write("You selected `%s`" % st.session_state.fname)
134
148
  else:
149
+ # reset the cache and resources if the user press reload button.
150
+ st.cache_data.clear()
151
+ st.cache_resource.clear()
135
152
  st.stop()
136
153
 
137
154
  ########## TIME AXIS ##############
@@ -164,8 +181,159 @@ date_df = pd.DataFrame(
164
181
  )
165
182
 
166
183
  st.session_state.date = pd.to_datetime(date_df)
167
-
168
- ######### MASK DATA ##############
184
+ st.session_state.date1 = pd.to_datetime(date_df)
185
+ st.session_state.date2 = pd.to_datetime(date_df)
186
+ st.session_state.date3 = pd.to_datetime(date_df)
187
+ st.session_state.ensemble_axis = np.arange(0, st.session_state.head.ensembles, 1)
188
+ st.session_state.axis_option = "time"
189
+
190
+
191
+ # ---------- Initialize all options -------------
192
+ # ------------------------
193
+ # Page: Download Raw File
194
+ # ------------------------
195
+ # Widgets
196
+ st.session_state.add_attributes_DRW = "No"
197
+ st.session_state.axis_option_DRW = "time"
198
+ st.session_state.rawnc_download_DRW = False
199
+ st.session_state.vleadnc_download_DRW = False
200
+ st.session_state.rawcsv_option_DRW = "Velocity"
201
+ st.session_state.rawcsv_beam_DRW = 1
202
+ st.session_state.rawcsv_download_DRW = False
203
+
204
+ # ------------------
205
+ # Page: Sensor Test
206
+ # ------------------
207
+ st.session_state.isSensorTest = False
208
+ st.session_state.isFirstSensorVisit = True
209
+
210
+ # -- Tab 1: Depth Correction
211
+ st.session_state.isDepthModified_ST = False
212
+ # Widgets
213
+ # Options: "Fixed Value", "File Upload"
214
+ st.session_state.depthoption_ST = "Fixed Value"
215
+ st.session_state.isFixedDepth_ST = False
216
+ st.session_state.fixeddepth_ST = 0
217
+ st.session_state.isUploadDepth_ST = False
218
+
219
+ # -- Tab 2: Salinity Correction
220
+ st.session_state.isSalinityModified_ST = False
221
+ # Widgets
222
+ st.session_state.salinityoption_ST = "Fixed Value"
223
+ st.session_state.isFixedSalinity_ST = False
224
+ st.session_state.fixedsalinity_ST = 35
225
+ st.session_state.isUploadSalinity_ST = False
226
+
227
+ # -- Tab 3: Temperature Correction
228
+ st.session_state.isTemperatureModified_ST = False
229
+ # Widgets
230
+ st.session_state.temperatureoption_ST = "Fixed Value"
231
+ st.session_state.isFixedTemperature_ST = False
232
+ st.session_state.fixedtemperature_ST = 0
233
+ st.session_state.isUploadTemperature_ST = False
234
+
235
+ # -- Tab 7: Pitch, Roll, Velocity Correction
236
+ st.session_state.isRollCheck_ST = False
237
+ st.session_state.isPitchCheck_ST = False
238
+ st.session_state.isVelocityModifiedSound_ST = False
239
+ # Widgets
240
+ st.session_state.roll_cutoff_ST = 359
241
+ st.session_state.pitch_cutoff_ST = 359
242
+
243
+ # ------------------
244
+ # Page: QC Test
245
+ # ------------------
246
+ # Global Test
247
+ st.session_state.isQCTest = False
248
+ st.session_state.isFirstQCVisit = True
249
+
250
+ # Tab 2: Apply QC
251
+ st.session_state.isQCCheck_QCT = False
252
+ # Widgets
253
+ st.session_state.ct_QCT = 64
254
+ st.session_state.et_QCT = 0
255
+ st.session_state.evt_QCT = 2000
256
+ st.session_state.ft_QCT = 50
257
+ st.session_state.is3beam_QCT = True
258
+ st.session_state.pgt_QCT = 0
259
+
260
+ # Data Modifications
261
+ st.session_state.isBeamModified_QCT = False
262
+ # Widgets
263
+ st.session_state.beam_direction_QCT = st.session_state.beam_direction
264
+
265
+ # ------------------
266
+ # Page: Profile Test
267
+ # ------------------
268
+ st.session_state.isProfileTest = False
269
+ st.session_state.isFirstProfileVisit = True
270
+
271
+ # Tab1: Trim Ends
272
+ st.session_state.isTrimEndsCheck_PT = False
273
+ # Widgets
274
+ st.session_state.start_ens_PT = 0
275
+ st.session_state.end_ens_PT = st.session_state.head.ensembles
276
+
277
+ # Tab2: Cutbins - Sidelobe
278
+ st.session_state.isCutBinSideLobeCheck_PT = False
279
+ st.session_state.extra_cells_PT = 0
280
+ st.session_state.water_depth_PT = 0
281
+
282
+ # Tab3: Cutbins - Manual
283
+ st.session_state.isCutBinManualCheck_PT = False
284
+
285
+ # Tab4: Regrid
286
+ st.session_state.isRegridCheck_PT = False
287
+ st.session_state.end_cell_option_PT = "Cell"
288
+ st.session_state.interpolate_PT = "nearest"
289
+ st.session_state.manualdepth_PT = 0
290
+
291
+ # ------------------
292
+ # Page: Velocity Test
293
+ # ------------------
294
+ # Global Test
295
+ st.session_state.isVelocityTest = False
296
+ # Check if visiting the page first time
297
+ st.session_state.isFirstVelocityVisit = True
298
+ # Local Tests:
299
+ # Tab1: Magnetic Declination
300
+ st.session_state.isMagnetCheck_VT = False
301
+ # OPTIONS: pygeomag, API, Manual
302
+ st.session_state.magnet_method_VT = "pygeomag"
303
+ st.session_state.magnet_lat_VT = 0
304
+ st.session_state.magnet_lon_VT = 0
305
+ st.session_state.magnet_year_VT = 2025
306
+ st.session_state.magnet_depth_VT = 0
307
+ st.session_state.magnet_user_input_VT = 0
308
+
309
+ # Tab2: Velocity Cutoff
310
+ st.session_state.isCutoffCheck_VT = False
311
+ st.session_state.maxuvel_VT = 250
312
+ st.session_state.maxvvel_VT = 250
313
+ st.session_state.maxwvel_VT = 15
314
+
315
+ # Tab3: Despike
316
+ st.session_state.isDespikeCheck_VT = False
317
+ st.session_state.despike_kernel_VT = 5
318
+ st.session_state.despike_cutoff_VT = 3
319
+
320
+ # Tab4: Flatline
321
+ st.session_state.isFlatlineCheck_VT = False
322
+ st.session_state.flatline_kernel_VT = 5
323
+ st.session_state.flatline_cutoff_VT = 3
324
+
325
+ # ------------------
326
+ # Page: Write File
327
+ # ------------------
328
+ st.session_state.isWriteFile = True
329
+ st.session_state.isAttributes = False
330
+ st.session_state.mask_data_WF = "Yes"
331
+ # FileTypes: NetCDF, CSV
332
+ st.session_state.file_type_WF = "NetCDF"
333
+ st.session_state.isProcessedNetcdfDownload_WF = True
334
+ st.session_state.isProcessedCSVDownload_WF = False
335
+
336
+ # MASK DATA
169
337
  # The velocity data has missing values due to the cutoff
170
338
  # criteria used before deployment. The `default_mask` uses
171
339
  # the velocity to create a mask. This mask file is stored
@@ -174,16 +342,17 @@ st.session_state.date = pd.to_datetime(date_df)
174
342
  # WARNING: Never Change `st.session_state.orig_mask` in the code!
175
343
  #
176
344
  if "orig_mask" not in st.session_state:
177
- st.session_state.orig_mask = default_mask(
178
- st.session_state.flead, st.session_state.velocity
179
- )
345
+ ds = st.session_state.ds
346
+ st.session_state.orig_mask = default_mask(ds)
180
347
 
181
- # Checks if the following quality checks are carried out
182
- st.session_state.isQCMask = False
183
- st.session_state.isProfileMask = False
184
- st.session_state.isGrid = False
185
- st.session_state.isGridSave = False
186
- st.session_state.isVelocityMask = False
348
+ # ----------------------
349
+ # Page returning options
350
+ # ----------------------
351
+ # This checks if we have returned back to the page after saving the data
352
+ st.session_state.isSensorPageReturn = False
353
+ st.session_state.isQCPageReturn = False
354
+ st.session_state.isProfilePageReturn = False
355
+ st.session_state.isVelocityPageReturn = False
187
356
 
188
357
  ########## FILE HEADER ###############
189
358
  st.header("File Header", divider="blue")
@@ -260,10 +429,18 @@ if flead_check_button:
260
429
 
261
430
  flead_button = st.button("Fixed Leader")
262
431
  if flead_button:
432
+ # Pandas array should have all elements with same data type.
433
+ # Except Sl. no., which is np.uint64, rest are np.int64.
434
+ # Convert all datatype to uint64
435
+ fl_dict = st.session_state.flead.field().items()
436
+ new_dict = {}
437
+ for key, value in fl_dict:
438
+ new_dict[key] = value.astype(np.uint64)
439
+
263
440
  df = pd.DataFrame(
264
441
  {
265
- "Fields": st.session_state.flead.field().keys(),
266
- "Values": st.session_state.flead.field().values(),
442
+ "Fields": new_dict.keys(),
443
+ "Values": new_dict.values(),
267
444
  }
268
445
  )
269
446
  st.dataframe(df, use_container_width=True)
@@ -281,4 +458,3 @@ with right:
281
458
  df = df.astype("str")
282
459
  st.write((df.style.map(color_bool2)))
283
460
  # st.dataframe(df)
284
-
@@ -84,45 +84,81 @@ The ordinate (y-axis) for the heatmap is `bins` as the depth correction is not a
84
84
  xbutton = st.radio("Select an x-axis to plot", ["time", "ensemble"], horizontal=True)
85
85
 
86
86
 
87
+ tab1, tab2, tab3, tab4 = st.tabs(["Primary Data", "Variable Leader", "Fixed Leader", "Advanced"])
88
+
89
+ with tab3:
87
90
  # Fixed Leader Plots
88
- st.header("Fixed Leader", divider="blue")
89
- fbutton = st.radio("Select a dynamic variable to plot:", fdata.keys(), horizontal=True)
90
- lineplot(fdata[fbutton], fbutton, xaxis=str(xbutton))
91
+ st.header("Fixed Leader", divider="blue")
92
+ fbutton = st.radio("Select a dynamic variable to plot:", fdata.keys(), horizontal=True)
93
+ lineplot(fdata[fbutton], fbutton, xaxis=str(xbutton))
91
94
 
95
+ with tab2:
92
96
  # Variable Leader Plots
93
- st.header("Variable Leader", divider="blue")
94
- vbutton = st.radio("Select a dynamic variable to plot:", vdata.keys(), horizontal=True)
95
- lineplot(vdata[vbutton], vbutton, xaxis=str(xbutton))
96
-
97
- basic_options = [
98
- "Pressure",
99
- "Temperature",
100
- "Salinity",
101
- "Depth of Transducer",
102
- "Heading",
103
- "Pitch",
104
- "Roll",
105
- ]
106
-
97
+ st.header("Variable Leader", divider="blue")
98
+ vbutton = st.radio("Select a dynamic variable to plot:", vdata.keys(), horizontal=True)
99
+ lineplot(vdata[vbutton], vbutton, xaxis=str(xbutton))
107
100
 
108
- st.header("Velocity, Echo Intensity, Correlation & Percent Good", divider="blue")
101
+ with tab1:
102
+ st.header("Velocity, Echo Intensity, Correlation & Percent Good", divider="blue")
109
103
 
110
104
 
111
- def call_plot(varname, beam, xaxis="time"):
112
- if varname == "Velocity":
113
- fillplot_plotly(velocity[beam - 1, :, :], title=varname, xaxis=xaxis)
114
- elif varname == "Echo":
115
- fillplot_plotly(echo[beam - 1, :, :], title=varname, xaxis=xaxis)
116
- elif varname == "Correlation":
117
- fillplot_plotly(correlation[beam - 1, :, :], title=varname, xaxis=xaxis)
118
- elif varname == "Percent Good":
119
- fillplot_plotly(pgood[beam - 1, :, :], title=varname, xaxis=xaxis)
105
+ def call_plot(varname, beam, xaxis="time"):
106
+ if varname == "Velocity":
107
+ fillplot_plotly(velocity[beam - 1, :, :], title=varname, xaxis=xaxis)
108
+ elif varname == "Echo":
109
+ fillplot_plotly(echo[beam - 1, :, :], title=varname, xaxis=xaxis)
110
+ elif varname == "Correlation":
111
+ fillplot_plotly(correlation[beam - 1, :, :], title=varname, xaxis=xaxis)
112
+ elif varname == "Percent Good":
113
+ fillplot_plotly(pgood[beam - 1, :, :], title=varname, xaxis=xaxis)
120
114
 
121
115
 
122
- var_option = st.selectbox(
123
- "Select a data type", ("Velocity", "Echo", "Correlation", "Percent Good")
124
- )
125
- beam = st.radio("Select beam", (1, 2, 3, 4), horizontal=True)
126
- call_plot(var_option, beam, xaxis=str(xbutton))
127
-
116
+ var_option = st.selectbox(
117
+ "Select a data type", ("Velocity", "Echo", "Correlation", "Percent Good")
118
+ )
119
+ beam = st.radio("Select beam", (1, 2, 3, 4), horizontal=True)
120
+ call_plot(var_option, beam, xaxis=str(xbutton))
121
+
122
+
123
+ with tab4:
124
+ st.header("Advanced Data", divider="blue")
125
+ adv_option = st.selectbox(
126
+ "Select a data type", ("Bit Result",
127
+ "ADC Channel",
128
+ "Error Status Word 1",
129
+ "Error Status Word 2",
130
+ "Error Status Word 3",
131
+ "Error Status Word 4"))
132
+ if adv_option == "Bit Result":
133
+ bitdata = st.session_state.vlead.bitresult()
134
+ st.subheader("BIT Result", divider="orange")
135
+ st.write("""
136
+ This field contains the results of Workhorse ADCPs builtin test functions.
137
+ A zero indicates a successful BIT result.
138
+ """)
139
+ bitbutton = st.radio("Select a dynamic variable to plot:", bitdata.keys(), horizontal=True)
140
+ lineplot(bitdata[bitbutton], bitbutton, xaxis=str(xbutton))
141
+
142
+ elif adv_option == "ADC Channel":
143
+ adcdata = st.session_state.vlead.adc_channel()
144
+ st.subheader("ADC Channel", divider="orange")
145
+ adcbutton = st.radio("Select a dynamic variable to plot:", adcdata.keys(), horizontal=True)
146
+ lineplot(adcdata[adcbutton], adcbutton, xaxis=str(xbutton))
147
+ elif adv_option == "Error Status Word 1":
148
+ errordata1 = st.session_state.vlead.error_status_word(esw=1)
149
+ st.subheader("Error Status Word", divider="orange")
150
+ errorbutton = st.radio("Select a dynamic variable to plot:", errordata1.keys(), horizontal=True)
151
+ lineplot(errordata1[errorbutton], errorbutton, xaxis=str(xbutton))
152
+ elif adv_option == "Error Status Word 2":
153
+ errordata2 = st.session_state.vlead.error_status_word(esw=2)
154
+ errorbutton = st.radio("Select a dynamic variable to plot:", errordata2.keys(), horizontal=True)
155
+ lineplot(errordata2[errorbutton], errorbutton, xaxis=str(xbutton))
156
+ elif adv_option == "Error Status Word 3":
157
+ errordata3 = st.session_state.vlead.error_status_word(esw=3)
158
+ errorbutton = st.radio("Select a dynamic variable to plot:", errordata3.keys(), horizontal=True)
159
+ lineplot(errordata3[errorbutton], errorbutton, xaxis=str(xbutton))
160
+ elif adv_option == "Error Status Word 4":
161
+ errordata4 = st.session_state.vlead.error_status_word(esw=4)
162
+ errorbutton = st.radio("Select a dynamic variable to plot:", errordata4.keys(), horizontal=True)
163
+ lineplot(errordata4[errorbutton], errorbutton, xaxis=str(xbutton))
128
164