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
@@ -20,18 +20,14 @@ if "fname" not in st.session_state:
|
|
20
20
|
if "rawfilename" not in st.session_state:
|
21
21
|
st.session_state.rawfilename = "rawfile.nc"
|
22
22
|
|
23
|
-
if "fleadfilename" not in st.session_state:
|
24
|
-
st.session_state.fleadfilename = "flead.nc"
|
25
|
-
|
26
23
|
if "vleadfilename" not in st.session_state:
|
27
24
|
st.session_state.vleadfilename = "vlead.nc"
|
28
25
|
|
29
26
|
if "attributes" not in st.session_state:
|
30
27
|
st.session_state.attributes = {}
|
31
|
-
|
32
|
-
if "
|
33
|
-
st.session_state.
|
34
|
-
|
28
|
+
|
29
|
+
if "add_attributes" not in st.session_state:
|
30
|
+
st.session_state.add_attributes = "No" # Default value
|
35
31
|
|
36
32
|
################ Functions #######################
|
37
33
|
@st.cache_data()
|
@@ -42,7 +38,6 @@ def file_access(uploaded_file):
|
|
42
38
|
f.write(uploaded_file.getvalue())
|
43
39
|
return path
|
44
40
|
|
45
|
-
|
46
41
|
@st.cache_data
|
47
42
|
def read_file(filepath):
|
48
43
|
ds = rd.ReadFile(st.session_state.fpath)
|
@@ -50,61 +45,25 @@ def read_file(filepath):
|
|
50
45
|
ds.fixensemble()
|
51
46
|
st.session_state.ds = ds
|
52
47
|
|
53
|
-
|
54
48
|
@st.cache_data
|
55
49
|
def file_write(path, axis_option, add_attributes=True):
|
56
50
|
tempdirname = tempfile.TemporaryDirectory(delete=False)
|
57
51
|
st.session_state.rawfilename = tempdirname.name + "/rawfile.nc"
|
58
|
-
|
52
|
+
|
59
53
|
if add_attributes:
|
60
|
-
wr.rawnc(
|
61
|
-
path,
|
62
|
-
st.session_state.rawfilename,
|
63
|
-
st.session_state.date1,
|
64
|
-
axis_option,
|
65
|
-
attributes=st.session_state.attributes,
|
66
|
-
)
|
54
|
+
wr.rawnc(path, st.session_state.rawfilename, st.session_state.date1, axis_option, attributes=st.session_state.attributes)
|
67
55
|
else:
|
68
|
-
wr.rawnc(
|
69
|
-
path, st.session_state.rawfilename, st.session_state.date1, axis_option
|
70
|
-
)
|
71
|
-
|
72
|
-
@st.cache_data
|
73
|
-
def file_write_flead(path, axis_option, add_attributes=True):
|
74
|
-
tempvardirname = tempfile.TemporaryDirectory(delete=False)
|
75
|
-
st.session_state.fleadfilename = tempvardirname.name + "/flead.nc"
|
76
|
-
|
77
|
-
if add_attributes:
|
78
|
-
wr.flead_nc(
|
79
|
-
path,
|
80
|
-
st.session_state.fleadfilename,
|
81
|
-
st.session_state.date2,
|
82
|
-
axis_option,
|
83
|
-
attributes=st.session_state.attributes,
|
84
|
-
)
|
85
|
-
else:
|
86
|
-
wr.flead_nc(
|
87
|
-
path, st.session_state.fleadfilename, st.session_state.date2, axis_option
|
88
|
-
)
|
56
|
+
wr.rawnc(path, st.session_state.rawfilename, st.session_state.date1,axis_option)
|
89
57
|
|
90
58
|
@st.cache_data
|
91
59
|
def file_write_vlead(path, axis_option, add_attributes=True):
|
92
60
|
tempvardirname = tempfile.TemporaryDirectory(delete=False)
|
93
61
|
st.session_state.vleadfilename = tempvardirname.name + "/vlead.nc"
|
94
|
-
|
62
|
+
|
95
63
|
if add_attributes:
|
96
|
-
wr.vlead_nc(
|
97
|
-
path,
|
98
|
-
st.session_state.vleadfilename,
|
99
|
-
st.session_state.date3,
|
100
|
-
axis_option,
|
101
|
-
attributes=st.session_state.attributes,
|
102
|
-
)
|
64
|
+
wr.vlead_nc(path, st.session_state.vleadfilename, st.session_state.date2, axis_option, attributes=st.session_state.attributes)
|
103
65
|
else:
|
104
|
-
wr.vlead_nc(
|
105
|
-
path, st.session_state.vleadfilename, st.session_state.date3, axis_option
|
106
|
-
)
|
107
|
-
|
66
|
+
wr.vlead_nc(path, st.session_state.vleadfilename, st.session_state.date2, axis_option)
|
108
67
|
|
109
68
|
if "axis_option" not in st.session_state:
|
110
69
|
st.session_state.axis_option = "ensemble" # Default value
|
@@ -113,67 +72,51 @@ if "axis_option" not in st.session_state:
|
|
113
72
|
st.header("NetCDF File", divider="blue")
|
114
73
|
|
115
74
|
# Option to add attributes
|
116
|
-
|
117
|
-
"Do you want to add attributes to the NetCDF file?", ["No", "Yes"], horizontal=True
|
118
|
-
)
|
75
|
+
add_attributes = st.radio("Do you want to add attributes to the NetCDF file?", ["No", "Yes"], horizontal=True)
|
119
76
|
|
120
|
-
if
|
77
|
+
if add_attributes == "Yes":
|
121
78
|
st.write("### Please fill in the attributes:")
|
122
|
-
|
79
|
+
|
123
80
|
# Two-column layout
|
124
81
|
col1, col2 = st.columns(2)
|
125
|
-
|
82
|
+
|
126
83
|
with col1:
|
127
|
-
st.session_state.attributes[
|
128
|
-
st.session_state.attributes[
|
129
|
-
st.session_state.attributes[
|
130
|
-
st.session_state.attributes[
|
131
|
-
st.session_state.attributes[
|
132
|
-
|
133
|
-
)
|
134
|
-
|
135
|
-
"Deployment Date"
|
136
|
-
)
|
137
|
-
st.session_state.attributes["Recovery_Date"] = st.date_input("Recovery Date")
|
84
|
+
st.session_state.attributes['Cruise_No.'] = st.text_input("Cruise No.")
|
85
|
+
st.session_state.attributes['Ship_Name'] = st.text_input("Ship Name")
|
86
|
+
st.session_state.attributes['Project_No.'] = st.text_input("Project No.")
|
87
|
+
st.session_state.attributes['Water_Depth_m'] = st.text_input("Water Depth (m)")
|
88
|
+
st.session_state.attributes['Deployment_Depth_m'] = st.text_input("Deployment Depth (m)")
|
89
|
+
st.session_state.attributes['Deployment_Date'] = st.date_input("Deployment Date")
|
90
|
+
st.session_state.attributes['Recovery_Date'] = st.date_input("Recovery Date")
|
91
|
+
|
138
92
|
|
139
93
|
with col2:
|
140
|
-
st.session_state.attributes[
|
141
|
-
st.session_state.attributes[
|
142
|
-
st.session_state.attributes[
|
143
|
-
st.session_state.attributes[
|
144
|
-
st.session_state.attributes[
|
145
|
-
|
146
|
-
)
|
147
|
-
st.session_state.attributes["Contact"] = st.text_input("Contact")
|
148
|
-
st.session_state.attributes["Comments"] = st.text_area("Comments")
|
94
|
+
st.session_state.attributes['Latitude'] = st.text_input("Latitude")
|
95
|
+
st.session_state.attributes['Longitude'] = st.text_input("Longitude")
|
96
|
+
st.session_state.attributes['Platform_Type'] = st.text_input("Platform Type")
|
97
|
+
st.session_state.attributes['Participants'] = st.text_area("Participants")
|
98
|
+
st.session_state.attributes['File_created_by'] = st.text_input("File created by")
|
99
|
+
st.session_state.attributes['Contact'] = st.text_input("Contact")
|
100
|
+
st.session_state.attributes['Comments'] = st.text_area("Comments")
|
149
101
|
|
150
102
|
st.write("Attributes will be added to the NetCDF file once you submit.")
|
151
103
|
|
152
104
|
# Dropdown for axis_option
|
153
|
-
|
105
|
+
axis_option = st.selectbox(
|
154
106
|
"Select x-axis option:",
|
155
|
-
options=["
|
156
|
-
index=0
|
107
|
+
options=["ensemble", "time"],
|
108
|
+
index=0 # Default to "ensemble"
|
157
109
|
)
|
158
110
|
|
159
111
|
# Ensure it is passed correctly
|
160
|
-
|
112
|
+
st.session_state.axis_option = axis_option
|
161
113
|
|
162
114
|
# Buttons to generate files
|
163
|
-
|
164
|
-
|
165
|
-
"Generate Raw Fixed Leader NetCDF File"
|
166
|
-
)
|
167
|
-
st.session_state.vleadnc_download_DRW = st.button(
|
168
|
-
"Generate Raw Variable Leader NetCDF File"
|
169
|
-
)
|
115
|
+
download_button = st.button("Generate Raw NetCDF File")
|
116
|
+
download_var_button = st.button("Generate Raw Variable Leader NetCDF File")
|
170
117
|
|
171
|
-
if
|
172
|
-
file_write(
|
173
|
-
st.session_state.fpath,
|
174
|
-
st.session_state.axis_option_DRW,
|
175
|
-
st.session_state.add_attributes_DRW == "Yes",
|
176
|
-
)
|
118
|
+
if download_button:
|
119
|
+
file_write(st.session_state.fpath, st.session_state.axis_option , add_attributes == "Yes")
|
177
120
|
st.write(st.session_state.rawfilename)
|
178
121
|
with open(st.session_state.rawfilename, "rb") as file:
|
179
122
|
st.download_button(
|
@@ -182,26 +125,8 @@ if st.session_state.rawnc_download_DRW:
|
|
182
125
|
file_name="rawfile.nc",
|
183
126
|
)
|
184
127
|
|
185
|
-
if
|
186
|
-
|
187
|
-
st.session_state.fpath,
|
188
|
-
st.session_state.axis_option,
|
189
|
-
st.session_state.add_attributes_DRW == "Yes",
|
190
|
-
)
|
191
|
-
st.write(st.session_state.fleadfilename)
|
192
|
-
with open(st.session_state.fleadfilename, "rb") as file:
|
193
|
-
st.download_button(
|
194
|
-
label="Download Fixed Leader",
|
195
|
-
data=file,
|
196
|
-
file_name="flead.nc",
|
197
|
-
)
|
198
|
-
|
199
|
-
if st.session_state.vleadnc_download_DRW:
|
200
|
-
file_write_vlead(
|
201
|
-
st.session_state.fpath,
|
202
|
-
st.session_state.axis_option,
|
203
|
-
st.session_state.add_attributes_DRW == "Yes",
|
204
|
-
)
|
128
|
+
if download_var_button:
|
129
|
+
file_write_vlead(st.session_state.fpath, st.session_state.axis_option, add_attributes == "Yes")
|
205
130
|
st.write(st.session_state.vleadfilename)
|
206
131
|
with open(st.session_state.vleadfilename, "rb") as file:
|
207
132
|
st.download_button(
|
@@ -210,7 +135,6 @@ if st.session_state.vleadnc_download_DRW:
|
|
210
135
|
file_name="vlead.nc",
|
211
136
|
)
|
212
137
|
|
213
|
-
|
214
138
|
def download_csv_with_ensemble(data, filename):
|
215
139
|
# Create ensemble numbers from 1 to the number of rows in the data
|
216
140
|
ensembles = np.arange(1, len(next(iter(data.values()))) + 1)
|
@@ -220,62 +144,60 @@ def download_csv_with_ensemble(data, filename):
|
|
220
144
|
df.insert(0, "RDI_Ensemble", ensembles) # Add ensemble numbers as the first column
|
221
145
|
|
222
146
|
# Export the DataFrame as a CSV
|
223
|
-
csv = df.to_csv(index=False).encode(
|
147
|
+
csv = df.to_csv(index=False).encode('utf-8')
|
224
148
|
return st.download_button(
|
225
149
|
label=f"Download {filename} as CSV",
|
226
150
|
data=csv,
|
227
151
|
file_name=f"{filename}.csv",
|
228
|
-
mime=
|
152
|
+
mime='text/csv',
|
229
153
|
)
|
230
|
-
|
231
|
-
|
154
|
+
|
232
155
|
def download_csv(data, filename):
|
233
156
|
# Convert data to DataFrame if it's not already one
|
234
157
|
if isinstance(data, dict):
|
235
158
|
df = pd.DataFrame.from_dict(data, orient="index").T
|
236
159
|
else:
|
237
160
|
df = pd.DataFrame(data)
|
238
|
-
|
161
|
+
|
239
162
|
# Export the DataFrame as a CSV
|
240
|
-
csv = df.to_csv(index=False).encode(
|
163
|
+
csv = df.to_csv(index=False).encode('utf-8')
|
241
164
|
return st.download_button(
|
242
165
|
label=f"Download {filename} as CSV",
|
243
166
|
data=csv,
|
244
167
|
file_name=f"{filename}.csv",
|
245
|
-
mime=
|
168
|
+
mime='text/csv',
|
246
169
|
)
|
247
|
-
|
248
|
-
|
170
|
+
|
171
|
+
|
249
172
|
def download_csv1(data, filename):
|
250
173
|
# Convert data to DataFrame if it's not already one
|
251
174
|
if isinstance(data, dict):
|
252
175
|
df = pd.DataFrame.from_dict(data, orient="index").T
|
253
176
|
else:
|
254
177
|
df = pd.DataFrame(data)
|
255
|
-
|
178
|
+
|
256
179
|
# Create ensemble and depth arrays
|
257
180
|
ensembles = np.arange(1, df.shape[0] + 1)
|
258
181
|
depths = np.arange(1, df.shape[1] + 1)
|
259
|
-
|
182
|
+
|
260
183
|
# Add ensemble numbers as the first column
|
261
|
-
df.insert(0,
|
262
|
-
|
184
|
+
df.insert(0, 'Ensemble', ensembles)
|
185
|
+
|
263
186
|
# Transpose the DataFrame to switch rows and columns
|
264
187
|
df = df.T
|
265
|
-
|
188
|
+
|
266
189
|
# Add depth values as the first row
|
267
|
-
df.insert(0,
|
268
|
-
|
190
|
+
df.insert(0, 'Depth', [''] + list(depths))
|
191
|
+
|
269
192
|
# Export the DataFrame as a CSV
|
270
|
-
csv = df.to_csv(index=False, header=False).encode(
|
193
|
+
csv = df.to_csv(index=False, header=False).encode('utf-8')
|
271
194
|
return st.download_button(
|
272
195
|
label=f"Download {filename} as CSV",
|
273
196
|
data=csv,
|
274
197
|
file_name=f"{filename}.csv",
|
275
|
-
mime=
|
198
|
+
mime='text/csv',
|
276
199
|
)
|
277
200
|
|
278
|
-
|
279
201
|
# Load data
|
280
202
|
fdata = st.session_state.flead.fleader
|
281
203
|
vdata = st.session_state.vlead.vleader
|
@@ -293,36 +215,25 @@ X, Y = np.meshgrid(x, y)
|
|
293
215
|
st.header("Download Raw Data CSV File", divider="blue")
|
294
216
|
|
295
217
|
# Selection for the data category
|
296
|
-
|
218
|
+
data_type = st.selectbox(
|
297
219
|
"Select data type to download:",
|
298
|
-
[
|
299
|
-
"Velocity",
|
300
|
-
"Echo Intensity",
|
301
|
-
"Correlation",
|
302
|
-
"Percent Good",
|
303
|
-
"Variable Leader",
|
304
|
-
"Fixed Leader",
|
305
|
-
],
|
220
|
+
["Fixed Leader", "Variable Leader", "Velocity", "Echo Intensity", "Correlation", "Percent Good"]
|
306
221
|
)
|
307
222
|
|
308
223
|
# Show corresponding variable options based on selection
|
309
|
-
if
|
224
|
+
if data_type == "Fixed Leader":
|
310
225
|
# Combine all variables of Fixed Leader into one DataFrame
|
311
226
|
f_combined_data = {var: fdata[var] for var in fdata.keys()}
|
312
227
|
download_csv_with_ensemble(f_combined_data, "Fixed_Leader_All_Variables")
|
313
228
|
|
314
|
-
elif
|
229
|
+
elif data_type == "Variable Leader":
|
315
230
|
# Combine all variables of Variable Leader into one DataFrame
|
316
231
|
v_combined_data = {var: vdata[var] for var in vdata.keys()}
|
317
232
|
download_csv(v_combined_data, "Variable_Leader_All_Variables")
|
318
233
|
|
319
234
|
else:
|
320
|
-
|
321
|
-
"Select beam to download", (1, 2, 3, 4), horizontal=True
|
322
|
-
)
|
235
|
+
beam_download = st.radio("Select beam to download", (1, 2, 3, 4), horizontal=True)
|
323
236
|
|
324
|
-
data_type = st.session_state.rawcsv_option_DRW
|
325
|
-
beam_download = st.session_state.rawcsv_beam_DRW
|
326
237
|
if data_type == "Velocity":
|
327
238
|
download_data = velocity[beam_download - 1, :, :]
|
328
239
|
elif data_type == "Echo Intensity":
|
@@ -333,3 +244,4 @@ else:
|
|
333
244
|
download_data = pgood[beam_download - 1, :, :]
|
334
245
|
|
335
246
|
download_csv1(download_data, f"{data_type}_Beam_{beam_download}")
|
247
|
+
|
@@ -0,0 +1,334 @@
|
|
1
|
+
import numpy as np
|
2
|
+
import pandas as pd
|
3
|
+
import plotly.express as px
|
4
|
+
import plotly.graph_objects as go
|
5
|
+
import streamlit as st
|
6
|
+
from plotly.subplots import make_subplots
|
7
|
+
from plotly_resampler import FigureResampler
|
8
|
+
from streamlit.runtime.state import session_state
|
9
|
+
from utils.signal_quality import ev_check, false_target, pg_check, qc_check
|
10
|
+
|
11
|
+
if "flead" not in st.session_state:
|
12
|
+
st.write(":red[Please Select Data!]")
|
13
|
+
st.stop()
|
14
|
+
|
15
|
+
# `mask` holds the temporary changes in the page
|
16
|
+
# `qcmask` holds the final changes in the page
|
17
|
+
if "mask" not in st.session_state:
|
18
|
+
st.session_state.mask = np.copy(st.session_state.orig_mask)
|
19
|
+
|
20
|
+
if not st.session_state.isQCMask:
|
21
|
+
st.write(":grey[Creating a new mask file ...]")
|
22
|
+
st.session_state.qc_mask = np.copy(st.session_state.orig_mask)
|
23
|
+
st.session_state.isSubmit = False
|
24
|
+
else:
|
25
|
+
st.write(":grey[Working on a saved mask file ...]")
|
26
|
+
st.write(":orange[WARNING! QC test already completed. Reset to change settings.]")
|
27
|
+
reset_button1 = st.button("Reset Mask Data")
|
28
|
+
if reset_button1:
|
29
|
+
st.session_state.mask = np.copy(st.session_state.orig_mask)
|
30
|
+
st.session_state.qc_mask = np.copy(st.session_state.orig_mask)
|
31
|
+
st.write(":green[Mask data is reset to default]")
|
32
|
+
|
33
|
+
if "isThresh" not in st.session_state:
|
34
|
+
st.session_state.isThresh = False
|
35
|
+
|
36
|
+
# Load data
|
37
|
+
flobj = st.session_state.flead
|
38
|
+
vlobj = st.session_state.vlead
|
39
|
+
velocity = st.session_state.velocity
|
40
|
+
echo = st.session_state.echo
|
41
|
+
correlation = st.session_state.correlation
|
42
|
+
pgood = st.session_state.pgood
|
43
|
+
ensembles = st.session_state.head.ensembles
|
44
|
+
cells = flobj.field()["Cells"]
|
45
|
+
fdata = flobj.fleader
|
46
|
+
vdata = vlobj.vleader
|
47
|
+
x = np.arange(0, ensembles, 1)
|
48
|
+
y = np.arange(0, cells, 1)
|
49
|
+
|
50
|
+
|
51
|
+
@st.cache_data
|
52
|
+
def fillplot_plotly(data, colorscale="balance"):
|
53
|
+
fig = FigureResampler(go.Figure())
|
54
|
+
data1 = np.where(data == -32768, np.nan, data)
|
55
|
+
fig.add_trace(
|
56
|
+
go.Heatmap(z=data1[:, 0:-1], x=x, y=y, colorscale=colorscale, hoverongaps=False)
|
57
|
+
)
|
58
|
+
st.plotly_chart(fig)
|
59
|
+
|
60
|
+
|
61
|
+
@st.cache_data
|
62
|
+
def plot_noise(dep=0, rec=-1):
|
63
|
+
n = dep
|
64
|
+
m = rec
|
65
|
+
colorleft = [
|
66
|
+
"rgb(240, 255, 255)",
|
67
|
+
"rgb(115, 147, 179)",
|
68
|
+
"rgb(100, 149, 237)",
|
69
|
+
"rgb(15, 82, 186)",
|
70
|
+
]
|
71
|
+
colorright = [
|
72
|
+
"rgb(250, 200, 152)",
|
73
|
+
"rgb(255, 165, 0)",
|
74
|
+
"rgb(255, 95, 31)",
|
75
|
+
"rgb(139, 64, 0)",
|
76
|
+
]
|
77
|
+
fig = make_subplots(
|
78
|
+
rows=1,
|
79
|
+
cols=2,
|
80
|
+
subplot_titles=[
|
81
|
+
f"Deployment Ensemble ({x[n]+1})",
|
82
|
+
f"Recovery Ensemble ({x[m]+1})",
|
83
|
+
],
|
84
|
+
)
|
85
|
+
for i in range(4):
|
86
|
+
fig.add_trace(
|
87
|
+
go.Scatter(
|
88
|
+
x=echo[i, :, n],
|
89
|
+
y=y,
|
90
|
+
name=f"Beam (D) {i+1}",
|
91
|
+
line=dict(color=colorleft[i]),
|
92
|
+
),
|
93
|
+
row=1,
|
94
|
+
col=1,
|
95
|
+
)
|
96
|
+
for i in range(4):
|
97
|
+
fig.add_trace(
|
98
|
+
go.Scatter(
|
99
|
+
x=echo[i, :, m],
|
100
|
+
y=y,
|
101
|
+
name=f"Beam (R) {i+1}",
|
102
|
+
line=dict(color=colorright[i]),
|
103
|
+
),
|
104
|
+
row=1,
|
105
|
+
col=2,
|
106
|
+
)
|
107
|
+
|
108
|
+
fig.update_layout(height=600, width=800, title_text="Echo Intensity")
|
109
|
+
fig.update_xaxes(title="Echo (count)")
|
110
|
+
fig.update_yaxes(title="Cells")
|
111
|
+
st.plotly_chart(fig)
|
112
|
+
|
113
|
+
######### NOISE FLOOR IDENTIFICATION ##############
|
114
|
+
dn = rn = 1
|
115
|
+
st.header("Noise Floor Identification", divider="blue")
|
116
|
+
st.write(
|
117
|
+
"""
|
118
|
+
If the ADCP has collected data from the air either
|
119
|
+
before deployment or after recovery, this data can
|
120
|
+
be used to estimate the echo intensity threshold.
|
121
|
+
The plots below show the echo intensity from the first
|
122
|
+
and last ensembles. The noise level is typically around
|
123
|
+
30-40 counts throughout the entire profile.
|
124
|
+
"""
|
125
|
+
)
|
126
|
+
dn = st.number_input("Deployment Ensemble", x[0] + 1, x[-1] + 1, x[0] + 1)
|
127
|
+
# r = st.number_input("Recovery Ensemble", -1 * (x[-1] + 1), -1 * (x[0] + 1), -1)
|
128
|
+
rn = st.number_input("Recovery Ensemble", x[0] + 1, x[-1] + 1, x[-1] + 1)
|
129
|
+
dn = dn - 1
|
130
|
+
rn = rn - 1
|
131
|
+
|
132
|
+
plot_noise(dep=dn, rec=rn)
|
133
|
+
|
134
|
+
|
135
|
+
################## QC Test ###################
|
136
|
+
|
137
|
+
st.header("Quality Control Tests", divider="blue")
|
138
|
+
st.write("")
|
139
|
+
|
140
|
+
left, right = st.columns([1, 1])
|
141
|
+
with left:
|
142
|
+
st.write(""" Teledyne RDI recommends these quality control tests,
|
143
|
+
some of which can be configured before deployment.
|
144
|
+
The pre-deployment values configured for the ADCP are listed
|
145
|
+
in the table below. The noise-floor identification graph above
|
146
|
+
can assist in determining the echo intensity threshold.
|
147
|
+
For more information about these tests,
|
148
|
+
refer to *Acoustic Doppler Current Profiler Principles of
|
149
|
+
Operation: A Practical Primer* by Teledyne RDI.""")
|
150
|
+
fdata = st.session_state.flead.field()
|
151
|
+
st.divider()
|
152
|
+
st.write(":blue-background[Additional Information:]")
|
153
|
+
st.write(f"Number of Pings per Ensemble: `{fdata["Pings"]}`")
|
154
|
+
st.write(f"Number of Beams: `{fdata["Beams"]}`")
|
155
|
+
st.divider()
|
156
|
+
st.write(":red-background[Thresholds used during deployment:]")
|
157
|
+
thresh = pd.DataFrame(
|
158
|
+
[
|
159
|
+
["Correlation", fdata["Correlation Thresh"]],
|
160
|
+
["Error Velocity", fdata["Error Velocity Thresh"]],
|
161
|
+
["Echo Intensity", 0],
|
162
|
+
["False Target", fdata["False Target Thresh"]],
|
163
|
+
["Percentage Good", fdata["Percent Good Min"]],
|
164
|
+
],
|
165
|
+
columns=["Threshold", "Values"],
|
166
|
+
)
|
167
|
+
|
168
|
+
st.write(thresh)
|
169
|
+
|
170
|
+
with right:
|
171
|
+
with st.form(key="my_form"):
|
172
|
+
st.write("Would you like to apply new threshold?")
|
173
|
+
|
174
|
+
ct = st.number_input(
|
175
|
+
"Select Correlation Threshold",
|
176
|
+
0,
|
177
|
+
255,
|
178
|
+
fdata["Correlation Thresh"],
|
179
|
+
)
|
180
|
+
|
181
|
+
evt = st.number_input(
|
182
|
+
"Select Error Velocity Threshold",
|
183
|
+
0,
|
184
|
+
9999,
|
185
|
+
fdata["Error Velocity Thresh"],
|
186
|
+
)
|
187
|
+
|
188
|
+
et = st.number_input(
|
189
|
+
"Select Echo Intensity Threshold",
|
190
|
+
0,
|
191
|
+
255,
|
192
|
+
0,
|
193
|
+
)
|
194
|
+
|
195
|
+
ft = st.number_input(
|
196
|
+
"Select False Target Threshold",
|
197
|
+
0,
|
198
|
+
255,
|
199
|
+
fdata["False Target Thresh"],
|
200
|
+
)
|
201
|
+
|
202
|
+
option = st.selectbox(
|
203
|
+
"Would you like to use a three-beam solution?", (True, False)
|
204
|
+
)
|
205
|
+
|
206
|
+
pgt = st.number_input(
|
207
|
+
"Select Percent Good Threshold",
|
208
|
+
0,
|
209
|
+
100,
|
210
|
+
fdata["Percent Good Min"],
|
211
|
+
)
|
212
|
+
submit_button = st.form_submit_button(label="Submit")
|
213
|
+
|
214
|
+
|
215
|
+
mask = st.session_state.mask
|
216
|
+
with left:
|
217
|
+
if submit_button:
|
218
|
+
st.session_state.newthresh = pd.DataFrame(
|
219
|
+
[
|
220
|
+
["Correlation", str(ct)],
|
221
|
+
["Error Velocity", str(evt)],
|
222
|
+
["Echo Intensity", str(et)],
|
223
|
+
["False Target", str(ft)],
|
224
|
+
["Three Beam", str(option)],
|
225
|
+
["Percentage Good", str(pgt)],
|
226
|
+
],
|
227
|
+
columns=["Threshold", "Values"],
|
228
|
+
)
|
229
|
+
st.session_state.isThresh = True
|
230
|
+
# st.write(st.session_state.newthresh)
|
231
|
+
|
232
|
+
mask = pg_check(pgood, mask, pgt, threebeam=option)
|
233
|
+
mask = qc_check(correlation, mask, ct)
|
234
|
+
mask = qc_check(echo, mask, et)
|
235
|
+
mask = ev_check(velocity[3, :, :], mask, evt)
|
236
|
+
mask = false_target(echo, mask, ft, threebeam=True)
|
237
|
+
st.session_state.mask = mask
|
238
|
+
|
239
|
+
if st.session_state.isThresh:
|
240
|
+
st.write(":green-background[Current Thresholds]")
|
241
|
+
st.write(st.session_state.newthresh)
|
242
|
+
|
243
|
+
|
244
|
+
|
245
|
+
st.header("Mask File", divider="blue")
|
246
|
+
st.write(
|
247
|
+
"""
|
248
|
+
Displayed the mask file.
|
249
|
+
Ensure to save any necessary changes or apply additional thresholds if needed.
|
250
|
+
"""
|
251
|
+
)
|
252
|
+
|
253
|
+
|
254
|
+
if st.button("Display mask file"):
|
255
|
+
st.subheader("Default Mask File")
|
256
|
+
st.write(
|
257
|
+
"""
|
258
|
+
ADCP assigns missing values based on thresholds set before deployment.
|
259
|
+
These values cannot be recovered and the default
|
260
|
+
"""
|
261
|
+
)
|
262
|
+
fillplot_plotly(st.session_state.orig_mask, colorscale="greys")
|
263
|
+
|
264
|
+
|
265
|
+
st.subheader("Update Mask File")
|
266
|
+
st.write(
|
267
|
+
"""
|
268
|
+
Update, display and save the updated mask file after applying threshold.
|
269
|
+
If thresholds are not saved, default mask file is used.
|
270
|
+
"""
|
271
|
+
)
|
272
|
+
# values, counts = np.unique(mask, return_counts=True)
|
273
|
+
fillplot_plotly(st.session_state.mask, colorscale="greys")
|
274
|
+
|
275
|
+
############## SENSOR HEALTH ######################
|
276
|
+
st.header("Sensor Health", divider="blue")
|
277
|
+
st.write("The following details can be used to determine whether the additional sensors are functioning properly.")
|
278
|
+
# ################## Pressure Sensor Check ###################
|
279
|
+
# st.subheader("Pressure Sensor Check", divider="orange")
|
280
|
+
#
|
281
|
+
# st.subheader("Temperature Sensor Check", divider="orange")
|
282
|
+
#
|
283
|
+
# st.subheader("Tilt Sensor Check", divider="orange")
|
284
|
+
################## Fix Orientation ###################
|
285
|
+
st.subheader("Fix Orientation", divider="orange")
|
286
|
+
|
287
|
+
|
288
|
+
if st.session_state.beam_direction == 'Up':
|
289
|
+
beamalt = 'Down'
|
290
|
+
else:
|
291
|
+
beamalt = 'Up'
|
292
|
+
st.write(f"The current orientation of ADCP is `{st.session_state.beam_direction}`. Use the below option to correct the orientation.")
|
293
|
+
|
294
|
+
beamdir_select = st.radio(f'Change orientation to {beamalt}', ['No', 'Yes'])
|
295
|
+
if beamdir_select == 'Yes':
|
296
|
+
st.session_state.beam_direction = beamalt
|
297
|
+
st.write(f"The orientation changed to `{st.session_state.beam_direction}`")
|
298
|
+
|
299
|
+
|
300
|
+
|
301
|
+
|
302
|
+
################## Save Button #############
|
303
|
+
st.header("Save Data", divider="blue")
|
304
|
+
col1, col2 = st.columns([1, 1])
|
305
|
+
with col1:
|
306
|
+
save_mask_button = st.button(label="Save Mask Data")
|
307
|
+
|
308
|
+
if save_mask_button:
|
309
|
+
# st.session_state.mask = mask
|
310
|
+
st.session_state.qc_mask = np.copy(st.session_state.mask)
|
311
|
+
st.session_state.isQCMask = True
|
312
|
+
st.session_state.isProfileMask = False
|
313
|
+
st.session_state.isGridSave = False
|
314
|
+
st.session_state.isVelocityMask = False
|
315
|
+
st.write(":green[Mask file saved]")
|
316
|
+
else:
|
317
|
+
st.write(":red[Mask data not saved]")
|
318
|
+
with col2:
|
319
|
+
reset_mask_button = st.button("Reset mask Data")
|
320
|
+
if reset_mask_button:
|
321
|
+
st.session_state.mask = np.copy(st.session_state.orig_mask)
|
322
|
+
st.session_state.isQCMask = False
|
323
|
+
st.session_state.isGrid = False
|
324
|
+
st.session_state.isProfileMask = False
|
325
|
+
st.session_state.isVelocityMask = False
|
326
|
+
st.write(":green[Mask data is reset to default]")
|
327
|
+
|
328
|
+
|
329
|
+
|
330
|
+
|
331
|
+
|
332
|
+
|
333
|
+
|
334
|
+
|