pyadps 0.3.3b0__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 ADDED
@@ -0,0 +1,42 @@
1
+ import streamlit as st
2
+
3
+
4
+ def main():
5
+ st.set_page_config(
6
+ page_title="ADCP Data Processing Software",
7
+ page_icon=":world_map:️",
8
+ layout="wide",
9
+ initial_sidebar_state="auto",
10
+ menu_items={
11
+ "Get Help": "http://github.com/p-amol/adps",
12
+ "Report a bug": "http://github.com/adps/issues",
13
+ "About": "# Python ADCP Data Processing Software (PyADPS)",
14
+ },
15
+ )
16
+
17
+ """
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.
20
+
21
+ ## Features
22
+
23
+ * Access RDI ADCP binary files using Python 3
24
+ * Convert RDI binary files to netcdf
25
+ * Process ADCP data
26
+
27
+ ## Contribute
28
+ Issue Tracker: http://github.com/adps/issues
29
+ Source Code: http://github.com/p-amol/adps
30
+
31
+ ## Support
32
+ If you are having issues, please let us know.
33
+ We have a mailing list located at: adps-python@google-groups.com
34
+
35
+ ## License
36
+ The project is licensed under the MIT license.
37
+
38
+ """
39
+
40
+
41
+ if __name__ == "__main__":
42
+ main()
pyadps/__init__.py ADDED
@@ -0,0 +1,8 @@
1
+ #import utils.pyreadrdi
2
+ #import utils.readrdi
3
+ # pyadps/__init__.py
4
+
5
+ # Importing main modules and functions to simplify access
6
+ from pyadps.Home_Page import main as show_home_page
7
+ from pyadps.pages import *
8
+ from pyadps.utils import *
pyadps/__main__.py ADDED
@@ -0,0 +1,15 @@
1
+ # pyadps/__main__.py
2
+
3
+ import subprocess
4
+ import os
5
+
6
+ def main():
7
+ # Get the absolute path to Home_Page.py
8
+ current_dir = os.path.dirname(os.path.abspath(__file__))
9
+ home_page_path = os.path.join(current_dir, 'Home_Page.py')
10
+
11
+ # Run the Streamlit app
12
+ subprocess.run(["streamlit", "run", home_page_path])
13
+
14
+ if __name__ == "__main__":
15
+ main()
@@ -0,0 +1,458 @@
1
+ import os
2
+ import tempfile
3
+
4
+ import numpy as np
5
+ import pandas as pd
6
+ import streamlit as st
7
+ import utils.readrdi as rd
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")
13
+
14
+ """
15
+ Streamlit page to load ADCP binary file and display File Header
16
+ and Fixed Leader data
17
+ """
18
+
19
+ if "fname" not in st.session_state:
20
+ st.session_state.fname = "No file selected"
21
+
22
+ if "rawfilename" not in st.session_state:
23
+ st.session_state.rawfilename = "rawfile.nc"
24
+
25
+ if "vleadfilename" not in st.session_state:
26
+ st.session_state.vleadfilename = "vlead.nc"
27
+
28
+
29
+ ################ Functions #######################
30
+ @st.cache_data()
31
+ def file_access(uploaded_file):
32
+ """
33
+ Function creates temporary directory to store the uploaded file.
34
+ The path of the file is returned
35
+
36
+ Args:
37
+ uploaded_file (string): Name of the uploaded file
38
+
39
+ Returns:
40
+ path (string): Path of the uploaded file
41
+ """
42
+ temp_dir = tempfile.mkdtemp()
43
+ path = os.path.join(temp_dir, uploaded_file.name)
44
+ with open(path, "wb") as f:
45
+ f.write(uploaded_file.getvalue())
46
+ return path
47
+
48
+
49
+ def color_bool(val):
50
+ """
51
+ Takes a scalar and returns a string with
52
+ the css color property.
53
+ """
54
+ if isinstance(val, bool):
55
+ if val:
56
+ color = "green"
57
+ else:
58
+ color = "red"
59
+ else:
60
+ color = "orange"
61
+ return "color: %s" % color
62
+
63
+
64
+ def color_bool2(val):
65
+ """
66
+ Takes a scalar and returns a string with
67
+ the css color property. The following colors
68
+ are assinged for the string
69
+ "True": green,
70
+ "False": red
71
+ Any other string: orange
72
+
73
+ Args:
74
+ val (string): Any string data
75
+
76
+ Returns:
77
+ The input string with css color property added
78
+ """
79
+ if val == "True" or val == "Data type is healthy":
80
+ color = "green"
81
+ elif val == "False":
82
+ color = "red"
83
+ # elif val in st.session_state.ds.warnings.values():
84
+ # color = "orange"
85
+ else:
86
+ color = "orange"
87
+ return "color: %s" % color
88
+
89
+
90
+ @st.cache_data
91
+ def read_file(filepath):
92
+ ds = rd.ReadFile(st.session_state.fpath)
93
+ if not ds.isEnsembleEqual:
94
+ ds.fixensemble()
95
+ st.session_state.ds = ds
96
+ # return ds
97
+
98
+
99
+ uploaded_file = st.file_uploader("Upload RDI ADCP Binary File", type="000")
100
+
101
+ if uploaded_file is not None:
102
+ # st.cache_data.clear
103
+
104
+ # Get path
105
+ st.session_state.fpath = file_access(uploaded_file)
106
+ # Get data
107
+ read_file(st.session_state.fpath)
108
+ ds = st.session_state.ds
109
+ head = ds.fileheader
110
+ flead = ds.fixedleader
111
+ vlead = ds.variableleader
112
+ velocity = ds.velocity.data
113
+ correlation = ds.correlation.data
114
+ echo = ds.echo.data
115
+ pgood = ds.percentgood.data
116
+ beamdir = ds.fixedleader.system_configuration()["Beam Direction"]
117
+
118
+ st.session_state.fname = uploaded_file.name
119
+ st.session_state.head = ds.fileheader
120
+ st.session_state.flead = ds.fixedleader
121
+ st.session_state.vlead = ds.variableleader
122
+ st.session_state.velocity = ds.velocity.data
123
+ st.session_state.echo = ds.echo.data
124
+ st.session_state.correlation = ds.correlation.data
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
+
136
+ # st.session_state.flead = flead
137
+ # st.session_state.vlead = vlead
138
+ # st.session_state.head = head
139
+ # st.session_state.velocity = velocity
140
+ # st.session_state.echo = echo
141
+ # st.session_state.correlation = correlation
142
+ # st.session_state.pgood = pgood
143
+ st.write("You selected `%s`" % st.session_state.fname)
144
+
145
+ elif "flead" in st.session_state:
146
+ st.write("You selected `%s`" % st.session_state.fname)
147
+ else:
148
+ # reset the cache and resources if the user press reload button.
149
+ st.cache_data.clear()
150
+ st.cache_resource.clear()
151
+ st.stop()
152
+
153
+ ########## TIME AXIS ##############
154
+
155
+ # Time axis is extracted and stored as Pandas datetime
156
+ year = st.session_state.vlead.vleader["RTC Year"]
157
+ month = st.session_state.vlead.vleader["RTC Month"]
158
+ day = st.session_state.vlead.vleader["RTC Day"]
159
+ hour = st.session_state.vlead.vleader["RTC Hour"]
160
+ minute = st.session_state.vlead.vleader["RTC Minute"]
161
+ second = st.session_state.vlead.vleader["RTC Second"]
162
+
163
+ # Recent ADCP binary files have Y2K compliant clock. The Century
164
+ # is stored in`RTC Century`. As all files may not have this clock
165
+ # we have added 2000 to the year.
166
+ # CHECKS:
167
+ # Are all our data Y2K compliant?
168
+ # Should we give users the options to correct the data?
169
+
170
+ year = year + 2000
171
+ date_df = pd.DataFrame(
172
+ {
173
+ "year": year,
174
+ "month": month,
175
+ "day": day,
176
+ "hour": hour,
177
+ "minute": minute,
178
+ "second": second,
179
+ }
180
+ )
181
+
182
+ st.session_state.date = pd.to_datetime(date_df)
183
+ st.session_state.date1 = pd.to_datetime(date_df)
184
+ st.session_state.date2 = pd.to_datetime(date_df)
185
+ st.session_state.ensemble_axis = np.arange(0, st.session_state.head.ensembles, 1)
186
+ st.session_state.axis_option = "time"
187
+
188
+
189
+ # ---------- Initialize all options -------------
190
+ # ------------------------
191
+ # Page: Download Raw File
192
+ # ------------------------
193
+ # Widgets
194
+ st.session_state.add_attributes_DRW = "No"
195
+ st.session_state.axis_option_DRW = "time"
196
+ st.session_state.rawnc_download_DRW = False
197
+ st.session_state.vleadnc_download_DRW = False
198
+ st.session_state.rawcsv_option_DRW = "Velocity"
199
+ st.session_state.rawcsv_beam_DRW = 1
200
+ st.session_state.rawcsv_download_DRW = False
201
+
202
+ # ------------------
203
+ # Page: Sensor Test
204
+ # ------------------
205
+ st.session_state.isSensorTest = False
206
+ st.session_state.isFirstSensorVisit = True
207
+
208
+ # -- Tab 1: Depth Correction
209
+ st.session_state.isDepthModified_ST = False
210
+ # Widgets
211
+ # Options: "Fixed Value", "File Upload"
212
+ st.session_state.depthoption_ST = "Fixed Value"
213
+ st.session_state.isFixedDepth_ST = False
214
+ st.session_state.fixeddepth_ST = 0
215
+ st.session_state.isUploadDepth_ST = False
216
+
217
+ # -- Tab 2: Salinity Correction
218
+ st.session_state.isSalinityModified_ST = False
219
+ # Widgets
220
+ st.session_state.salinityoption_ST = "Fixed Value"
221
+ st.session_state.isFixedSalinity_ST = False
222
+ st.session_state.fixedsalinity_ST = 35
223
+ st.session_state.isUploadSalinity_ST = False
224
+
225
+ # -- Tab 3: Temperature Correction
226
+ st.session_state.isTemperatureModified_ST = False
227
+ # Widgets
228
+ st.session_state.temperatureoption_ST = "Fixed Value"
229
+ st.session_state.isFixedTemperature_ST = False
230
+ st.session_state.fixedtemperature_ST = 0
231
+ st.session_state.isUploadTemperature_ST = False
232
+
233
+ # -- Tab 7: Pitch, Roll, Velocity Correction
234
+ st.session_state.isRollCheck_ST = False
235
+ st.session_state.isPitchCheck_ST = False
236
+ st.session_state.isVelocityModifiedSound_ST = False
237
+ # Widgets
238
+ st.session_state.roll_cutoff_ST = 359
239
+ st.session_state.pitch_cutoff_ST = 359
240
+
241
+ # ------------------
242
+ # Page: QC Test
243
+ # ------------------
244
+ # Global Test
245
+ st.session_state.isQCTest = False
246
+ st.session_state.isFirstQCVisit = True
247
+
248
+ # Tab 2: Apply QC
249
+ st.session_state.isQCCheck_QCT = False
250
+ # Widgets
251
+ st.session_state.ct_QCT = 64
252
+ st.session_state.et_QCT = 0
253
+ st.session_state.evt_QCT = 2000
254
+ st.session_state.ft_QCT = 50
255
+ st.session_state.is3beam_QCT = True
256
+ st.session_state.pgt_QCT = 0
257
+
258
+ # Data Modifications
259
+ st.session_state.isBeamModified_QCT = False
260
+ # Widgets
261
+ st.session_state.beam_direction_QCT = st.session_state.beam_direction
262
+
263
+ # ------------------
264
+ # Page: Profile Test
265
+ # ------------------
266
+ st.session_state.isProfileTest = False
267
+ st.session_state.isFirstProfileVisit = True
268
+
269
+ # Tab1: Trim Ends
270
+ st.session_state.isTrimEndsCheck_PT = False
271
+ # Widgets
272
+ st.session_state.start_ens_PT = 0
273
+ st.session_state.end_ens_PT = st.session_state.head.ensembles
274
+
275
+ # Tab2: Cutbins - Sidelobe
276
+ st.session_state.isCutBinSideLobeCheck_PT = False
277
+ st.session_state.extra_cells_PT = 0
278
+ st.session_state.water_depth_PT = 0
279
+
280
+ # Tab3: Cutbins - Manual
281
+ st.session_state.isCutBinManualCheck_PT = False
282
+
283
+ # Tab4: Regrid
284
+ st.session_state.isRegridCheck_PT = False
285
+ st.session_state.end_cell_option_PT = "Cell"
286
+ st.session_state.interpolate_PT = "nearest"
287
+ st.session_state.manualdepth_PT = 0
288
+
289
+ # ------------------
290
+ # Page: Velocity Test
291
+ # ------------------
292
+ # Global Test
293
+ st.session_state.isVelocityTest = False
294
+ # Check if visiting the page first time
295
+ st.session_state.isFirstVelocityVisit = True
296
+ # Local Tests:
297
+ # Tab1: Magnetic Declination
298
+ st.session_state.isMagnetCheck_VT = False
299
+ # OPTIONS: pygeomag, API, Manual
300
+ st.session_state.magnet_method_VT = "pygeomag"
301
+ st.session_state.magnet_lat_VT = 0
302
+ st.session_state.magnet_lon_VT = 0
303
+ st.session_state.magnet_year_VT = 2025
304
+ st.session_state.magnet_depth_VT = 0
305
+ st.session_state.magnet_user_input_VT = 0
306
+
307
+ # Tab2: Velocity Cutoff
308
+ st.session_state.isCutoffCheck_VT = False
309
+ st.session_state.maxuvel_VT = 250
310
+ st.session_state.maxvvel_VT = 250
311
+ st.session_state.maxwvel_VT = 15
312
+
313
+ # Tab3: Despike
314
+ st.session_state.isDespikeCheck_VT = False
315
+ st.session_state.despike_kernal_VT = 5
316
+ st.session_state.despike_cutoff_VT = 3
317
+
318
+ # Tab4: Flatline
319
+ st.session_state.isFlatlineCheck_VT = False
320
+ st.session_state.flatline_kernal_VT = 5
321
+ st.session_state.flatline_cutoff_VT = 3
322
+
323
+ # ------------------
324
+ # Page: Write File
325
+ # ------------------
326
+ st.session_state.isWriteFile = True
327
+ st.session_state.isAttributes = False
328
+ st.session_state.mask_data_WF = "Yes"
329
+ # FileTypes: NetCDF, CSV
330
+ st.session_state.file_type_WF = "NetCDF"
331
+ st.session_state.isProcessedNetcdfDownload_WF = True
332
+ st.session_state.isProcessedCSVDownload_WF = False
333
+
334
+ # MASK DATA
335
+ # The velocity data has missing values due to the cutoff
336
+ # criteria used before deployment. The `default_mask` uses
337
+ # the velocity to create a mask. This mask file is stored
338
+ # in the session_state.
339
+ #
340
+ # WARNING: Never Change `st.session_state.orig_mask` in the code!
341
+ #
342
+ if "orig_mask" not in st.session_state:
343
+ ds = st.session_state.ds
344
+ st.session_state.orig_mask = default_mask(ds)
345
+
346
+ # ----------------------
347
+ # Page returning options
348
+ # ----------------------
349
+ # This checks if we have returned back to the page after saving the data
350
+ st.session_state.isSensorPageReturn = False
351
+ st.session_state.isQCPageReturn = False
352
+ st.session_state.isProfilePageReturn = False
353
+ st.session_state.isVelocityPageReturn = False
354
+
355
+ ########## FILE HEADER ###############
356
+ st.header("File Header", divider="blue")
357
+ st.write(
358
+ """
359
+ Header information is the first item sent by the ADCP. You may check the file size, total ensembles, and available data types. The function also checks if the total bytes and data types are uniform for all ensembles.
360
+ """
361
+ )
362
+
363
+ left1, right1 = st.columns(2)
364
+ with left1:
365
+ check_button = st.button("Check File Health")
366
+ if check_button:
367
+ cf = st.session_state.head.check_file()
368
+ if (
369
+ cf["File Size Match"]
370
+ and cf["Byte Uniformity"]
371
+ and cf["Data Type Uniformity"]
372
+ ):
373
+ st.write("Your file appears healthy! :sunglasses:")
374
+ else:
375
+ st.write("Your file appears corrupted! :worried:")
376
+
377
+ cf["File Size (MB)"] = "{:,.2f}".format(cf["File Size (MB)"])
378
+ st.write(f"Total no. of Ensembles: :green[{st.session_state.head.ensembles}]")
379
+ df = pd.DataFrame(cf.items(), columns=pd.array(["Check", "Details"]))
380
+ df = df.astype("str")
381
+ st.write(df.style.map(color_bool2, subset="Details"))
382
+ # st.write(df)
383
+ with right1:
384
+ datatype_button = st.button("Display Data Types")
385
+ if datatype_button:
386
+ st.write(
387
+ pd.DataFrame(
388
+ st.session_state.head.data_types(),
389
+ columns=pd.array(["Available Data Types"]),
390
+ )
391
+ )
392
+
393
+ if st.session_state.ds.isWarning:
394
+ st.write(
395
+ """
396
+ Warnings detected while reading. Data sets may still be available for processing.
397
+ Click `Display Warning` to display warnings for each data types.
398
+ """
399
+ )
400
+ warning_button = st.button("Display Warnings")
401
+ df2 = pd.DataFrame(
402
+ st.session_state.ds.warnings.items(),
403
+ columns=pd.array(["Data Type", "Warnings"]),
404
+ )
405
+ if warning_button:
406
+ st.write(df2.style.map(color_bool2, subset=["Warnings"]))
407
+
408
+ ############ FIXED LEADER #############
409
+
410
+ st.header("Fixed Leader (Static Variables)", divider="blue")
411
+ st.write(
412
+ """
413
+ Fixed Leader data refers to the non-dynamic WorkHorse ADCP data like the hardware information and the thresholds. Typically, values remain constant over time. They only change when you change certain commands, although there are occasional exceptions. You can confirm this using the :blue[**Fleader Uniformity Check**]. Click :blue[**Fixed Leader**] to display the values for the first ensemble.
414
+ """
415
+ )
416
+
417
+
418
+ flead_check_button = st.button("Fleader Uniformity Check")
419
+ if flead_check_button:
420
+ st.write("The following variables are non-uniform:")
421
+ for keys, values in st.session_state.flead.is_uniform().items():
422
+ if not values:
423
+ st.markdown(f":blue[**- {keys}**]")
424
+ st.write("Displaying all static variables")
425
+ df = pd.DataFrame(st.session_state.flead.is_uniform(), index=[0]).T
426
+ st.write(df.style.map(color_bool))
427
+
428
+ flead_button = st.button("Fixed Leader")
429
+ if flead_button:
430
+ # Pandas array should have all elements with same data type.
431
+ # Except Sl. no., which is np.uint64, rest are np.int64.
432
+ # Convert all datatype to uint64
433
+ fl_dict = st.session_state.flead.field().items()
434
+ new_dict = {}
435
+ for key, value in fl_dict:
436
+ new_dict[key] = value.astype(np.uint64)
437
+
438
+ df = pd.DataFrame(
439
+ {
440
+ "Fields": new_dict.keys(),
441
+ "Values": new_dict.values(),
442
+ }
443
+ )
444
+ st.dataframe(df, use_container_width=True)
445
+
446
+ left, centre, right = st.columns(3)
447
+ with left:
448
+ st.dataframe(st.session_state.flead.system_configuration())
449
+
450
+ with centre:
451
+ st.dataframe(st.session_state.flead.ez_sensor())
452
+ # st.write(output)
453
+ with right:
454
+ # st.write(st.session_state.flead.ex_coord_trans())
455
+ df = pd.DataFrame(st.session_state.flead.ex_coord_trans(), index=[0]).T
456
+ df = df.astype("str")
457
+ st.write((df.style.map(color_bool2)))
458
+ # st.dataframe(df)
@@ -0,0 +1,164 @@
1
+ import matplotlib.pyplot as plt
2
+ import numpy as np
3
+ import pandas as pd
4
+ import plotly.express as px
5
+ import plotly.graph_objects as go
6
+ import streamlit as st
7
+ from plotly_resampler import FigureResampler
8
+
9
+ if "flead" not in st.session_state:
10
+ st.write(":red[Please Select Data!]")
11
+ st.stop()
12
+
13
+ # Load data
14
+ fdata = st.session_state.flead.fleader
15
+ vdata = st.session_state.vlead.vleader
16
+ velocity = st.session_state.velocity
17
+ echo = st.session_state.echo
18
+ correlation = st.session_state.correlation
19
+ pgood = st.session_state.pgood
20
+
21
+ x = np.arange(0, st.session_state.head.ensembles, 1)
22
+ y = np.arange(0, fdata["Cells"][0], 1)
23
+
24
+ X, Y = np.meshgrid(x, y)
25
+
26
+
27
+ @st.cache_data
28
+ def fillplot_matplotlib(data):
29
+ fig, ax = plt.subplots()
30
+ cs = ax.contourf(X, Y, data)
31
+ fig.colorbar(cs)
32
+ st.pyplot(fig)
33
+
34
+
35
+ @st.cache_data
36
+ def fillplot_plotly(data, colorscale="balance", title="Data", xaxis="time"):
37
+ if xaxis == "time":
38
+ xdata = st.session_state.date
39
+ elif xaxis == "ensemble":
40
+ xdata = x
41
+ else:
42
+ xdata = x
43
+ fig = FigureResampler(go.Figure())
44
+ data1 = np.where(data == -32768, np.nan, data)
45
+ fig.add_trace(
46
+ go.Heatmap(
47
+ z=data1[:, 0:-1],
48
+ x=xdata,
49
+ y=y,
50
+ colorscale=colorscale,
51
+ hoverongaps=False,
52
+ )
53
+ )
54
+ fig.update_layout(
55
+ xaxis=dict(showline=True, mirror=True),
56
+ yaxis=dict(showline=True, mirror=True),
57
+ title_text=title,
58
+ )
59
+ st.plotly_chart(fig)
60
+
61
+
62
+ @st.cache_data
63
+ def lineplot(data, title, xaxis="time"):
64
+ if xaxis == "time":
65
+ df = pd.DataFrame({"date": st.session_state.date, title: data})
66
+ fig = px.line(df, x="date", y=title)
67
+ else:
68
+ df = pd.DataFrame({"ensemble": x, title: data})
69
+ fig = px.line(df, x="ensemble", y=title)
70
+
71
+ st.plotly_chart(fig)
72
+
73
+
74
+ # Introduction
75
+ st.header("View Raw Data", divider="orange")
76
+ st.write(
77
+ """
78
+ Displays all variables available in the raw file. No processing has been carried out.
79
+ Data might be missing because of the quality-check criteria used before deployment.\n
80
+ Either `time` or `ensemble` axis can be chosen as the abscissa (x-axis).
81
+ The ordinate (y-axis) for the heatmap is `bins` as the depth correction is not applied.
82
+ """
83
+ )
84
+ xbutton = st.radio("Select an x-axis to plot", ["time", "ensemble"], horizontal=True)
85
+
86
+
87
+ tab1, tab2, tab3, tab4 = st.tabs(["Primary Data", "Variable Leader", "Fixed Leader", "Advanced"])
88
+
89
+ with tab3:
90
+ # Fixed Leader Plots
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))
94
+
95
+ with tab2:
96
+ # Variable Leader Plots
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))
100
+
101
+ with tab1:
102
+ st.header("Velocity, Echo Intensity, Correlation & Percent Good", divider="blue")
103
+
104
+
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)
114
+
115
+
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))
164
+