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 +42 -0
- pyadps/__init__.py +8 -0
- pyadps/__main__.py +15 -0
- pyadps/pages/01_Read_File.py +458 -0
- pyadps/pages/02_View_Raw_Data.py +164 -0
- pyadps/pages/03_Download_Raw_File.py +298 -0
- pyadps/pages/04_Sensor_Health.py +905 -0
- pyadps/pages/05_QC_Test.py +476 -0
- pyadps/pages/06_Profile_Test.py +970 -0
- pyadps/pages/07_Velocity_Test.py +600 -0
- pyadps/pages/08_Write_File.py +574 -0
- pyadps/pages/09_Auto_process.py +62 -0
- pyadps/pages/__init__.py +0 -0
- pyadps/utils/__init__.py +12 -0
- pyadps/utils/autoprocess.py +530 -0
- pyadps/utils/metadata/config.ini +99 -0
- pyadps/utils/metadata/demo.000 +0 -0
- pyadps/utils/metadata/flmeta.json +422 -0
- pyadps/utils/metadata/vlmeta.json +567 -0
- pyadps/utils/plotgen.py +728 -0
- pyadps/utils/profile_test.py +556 -0
- pyadps/utils/pyreadrdi.py +969 -0
- pyadps/utils/readrdi.py +1610 -0
- pyadps/utils/script.py +201 -0
- pyadps/utils/sensor_health.py +120 -0
- pyadps/utils/signal_quality.py +455 -0
- pyadps/utils/velocity_test.py +200 -0
- pyadps/utils/writenc.py +339 -0
- pyadps-0.3.3b0.dist-info/LICENSE +8 -0
- pyadps-0.3.3b0.dist-info/METADATA +172 -0
- pyadps-0.3.3b0.dist-info/RECORD +33 -0
- pyadps-0.3.3b0.dist-info/WHEEL +4 -0
- pyadps-0.3.3b0.dist-info/entry_points.txt +5 -0
@@ -0,0 +1,970 @@
|
|
1
|
+
import numpy as np
|
2
|
+
import pandas as pd
|
3
|
+
|
4
|
+
# import plotly.express as px
|
5
|
+
import plotly.graph_objects as go
|
6
|
+
import streamlit as st
|
7
|
+
from plotly.subplots import make_subplots
|
8
|
+
from plotly_resampler import FigureResampler
|
9
|
+
from utils.profile_test import side_lobe_beam_angle, manual_cut_bins
|
10
|
+
from utils.profile_test import regrid2d, regrid3d
|
11
|
+
from utils.signal_quality import default_mask
|
12
|
+
|
13
|
+
# If no file is uploaded, then give a warning
|
14
|
+
if "flead" not in st.session_state:
|
15
|
+
st.write(":red[Please Select Data!]")
|
16
|
+
st.stop()
|
17
|
+
|
18
|
+
|
19
|
+
def reset_profiletest():
|
20
|
+
# Reset Global Test
|
21
|
+
st.session_state.isProfileTest = False
|
22
|
+
# Reset Local Tests
|
23
|
+
st.session_state.isTrimEndsCheck_PT = False
|
24
|
+
st.session_state.isCutBinSideLobeCheck_PT = False
|
25
|
+
st.session_state.isCutBinManualCheck_PT = False
|
26
|
+
st.session_state.isRegridCheck_PT = False
|
27
|
+
|
28
|
+
# Reset Page Return
|
29
|
+
st.session_state.isQCPageReturn = False
|
30
|
+
if not st.session_state.isQCTest:
|
31
|
+
st.session_state.isSensorPageReturn = False
|
32
|
+
|
33
|
+
# Reset Data
|
34
|
+
st.session_state.echo_regrid = np.copy(st.session_state.echo)
|
35
|
+
st.session_state.correlation_regrid = np.copy(st.session_state.correlation)
|
36
|
+
st.session_state.pgood_regrid = np.copy(st.session_state.pgood)
|
37
|
+
if st.session_state.isVelocityModifiedSound_ST:
|
38
|
+
st.session_state.velocity_regrid = np.copy(st.session_state.velocity_sensor)
|
39
|
+
st.session_state.velocity_temp = np.copy(st.session_state.velocity_sensor)
|
40
|
+
else:
|
41
|
+
st.session_state.velocity_regrid = np.copy(st.session_state.velocity)
|
42
|
+
st.session_state.velocity_temp = np.copy(st.session_state.velocity)
|
43
|
+
|
44
|
+
# Reset Mask Data
|
45
|
+
if st.session_state.isQCTest:
|
46
|
+
st.session_state.profile_mask_default = np.copy(st.session_state.qc_mask)
|
47
|
+
elif st.session_state.isSensorTest:
|
48
|
+
st.session_state.profile_mask_default = np.copy(st.session_state.sensor_mask)
|
49
|
+
else:
|
50
|
+
st.session_state.profile_mask_default = np.copy(st.session_state.orig_mask)
|
51
|
+
|
52
|
+
mask = st.session_state.profile_mask_default
|
53
|
+
st.session_state.profile_mask_temp = np.copy(mask)
|
54
|
+
st.session_state.profile_mask = np.copy(mask)
|
55
|
+
st.session_state.profile_mask_trimends = np.copy(mask)
|
56
|
+
st.session_state.profile_mask_sidelobe = np.copy(mask)
|
57
|
+
st.session_state.profile_mask_manual = np.copy(mask)
|
58
|
+
st.session_state.profile_mask_regrid = np.copy(mask)
|
59
|
+
|
60
|
+
st.session_state.sidelobe_displaymask = np.copy(mask)
|
61
|
+
st.session_state.manual_displaymask = np.copy(mask)
|
62
|
+
|
63
|
+
|
64
|
+
def hard_reset(option):
|
65
|
+
# Reset Global Test
|
66
|
+
st.session_state.isProfileTest = False
|
67
|
+
|
68
|
+
# Reset Local Tests
|
69
|
+
st.session_state.isTrimEndsCheck_PT = False
|
70
|
+
st.session_state.isCutBinSideLobeCheck_PT = False
|
71
|
+
st.session_state.isCutBinManualCheck_PT = False
|
72
|
+
st.session_state.isRegridCheck_PT = False
|
73
|
+
|
74
|
+
# Reset Page Return
|
75
|
+
st.session_state.isQCPageReturn = False
|
76
|
+
if not st.session_state.isQCTest:
|
77
|
+
st.session_state.isSensorPageReturn = False
|
78
|
+
|
79
|
+
# Reset Data
|
80
|
+
st.session_state.echo_regrid = np.copy(st.session_state.echo)
|
81
|
+
st.session_state.correlation_regrid = np.copy(st.session_state.correlation)
|
82
|
+
st.session_state.pgood_regrid = np.copy(st.session_state.pgood)
|
83
|
+
if st.session_state.isVelocityModifiedSound_ST:
|
84
|
+
st.session_state.velocity_regrid = np.copy(st.session_state.velocity_sensor)
|
85
|
+
st.session_state.velocity_temp = np.copy(st.session_state.velocity_sensor)
|
86
|
+
else:
|
87
|
+
st.session_state.velocity_regrid = np.copy(st.session_state.velocity)
|
88
|
+
st.session_state.velocity_temp = np.copy(st.session_state.velocity)
|
89
|
+
|
90
|
+
# Reset Mask Data based on user options
|
91
|
+
if option == "Sensor Test":
|
92
|
+
st.session_state.profile_mask_default = np.copy(st.session_state.sensor_mask)
|
93
|
+
if option == "QC Test":
|
94
|
+
st.session_state.profile_mask_default = np.copy(st.session_state.qc_mask)
|
95
|
+
elif option == "Default":
|
96
|
+
st.session_state.profile_mask_default = np.copy(st.session_state.orig_mask)
|
97
|
+
|
98
|
+
st.session_state.profile_mask = np.copy(st.session_state.profile_mask_default)
|
99
|
+
st.session_state.profile_mask_temp = np.copy(st.session_state.profile_mask_default)
|
100
|
+
st.session_state.profile_mask_trimends = np.copy(
|
101
|
+
st.session_state.profile_mask_default
|
102
|
+
)
|
103
|
+
st.session_state.profile_mask_sidelobe = np.copy(
|
104
|
+
st.session_state.profile_mask_default
|
105
|
+
)
|
106
|
+
st.session_state.profile_mask_manual = np.copy(
|
107
|
+
st.session_state.profile_mask_default
|
108
|
+
)
|
109
|
+
st.session_state.profile_mask_regrid = np.copy(
|
110
|
+
st.session_state.profile_mask_default
|
111
|
+
)
|
112
|
+
st.session_state.profile_mask_displaymask = np.copy(
|
113
|
+
st.session_state.profile_mask_default
|
114
|
+
)
|
115
|
+
|
116
|
+
|
117
|
+
# Load data
|
118
|
+
ds = st.session_state.ds
|
119
|
+
flobj = st.session_state.flead
|
120
|
+
vlobj = st.session_state.vlead
|
121
|
+
echo = st.session_state.echo
|
122
|
+
correlation = st.session_state.correlation
|
123
|
+
pgood = st.session_state.pgood
|
124
|
+
fdata = flobj.fleader
|
125
|
+
vdata = vlobj.vleader
|
126
|
+
|
127
|
+
# Setting up parameters for plotting graphs.
|
128
|
+
ensembles = st.session_state.head.ensembles
|
129
|
+
cells = flobj.field()["Cells"]
|
130
|
+
beams = flobj.field()["Beams"]
|
131
|
+
cell_size = flobj.field()["Depth Cell Len"]
|
132
|
+
bin1dist = flobj.field()["Bin 1 Dist"]
|
133
|
+
beam_angle = int(flobj.system_configuration()["Beam Angle"])
|
134
|
+
|
135
|
+
x = np.arange(0, ensembles, 1)
|
136
|
+
y = np.arange(0, cells, 1)
|
137
|
+
|
138
|
+
# Regrided data
|
139
|
+
# if "velocity_regrid" not in st.session_state:
|
140
|
+
# st.session_state.echo_regrid = np.copy(echo)
|
141
|
+
# st.session_state.velocity_regrid = np.copy(velocity)
|
142
|
+
# st.session_state.correlation_regrid = np.copy(correlation)
|
143
|
+
# st.session_state.pgood_regrid = np.copy(pgood)
|
144
|
+
# st.session_state.mask_regrid = np.copy(mask)
|
145
|
+
|
146
|
+
|
147
|
+
# @st.cache_data
|
148
|
+
def fillplot_plotly(
|
149
|
+
data, title="data", maskdata=None, missing=-32768, colorscale="balance"
|
150
|
+
):
|
151
|
+
fig = FigureResampler(go.Figure())
|
152
|
+
data = np.int32(data)
|
153
|
+
data1 = np.where(data == missing, np.nan, data)
|
154
|
+
fig.add_trace(
|
155
|
+
go.Heatmap(
|
156
|
+
z=data1,
|
157
|
+
x=x,
|
158
|
+
y=y,
|
159
|
+
colorscale=colorscale,
|
160
|
+
hoverongaps=False,
|
161
|
+
)
|
162
|
+
)
|
163
|
+
if maskdata is not None:
|
164
|
+
fig.add_trace(
|
165
|
+
go.Heatmap(
|
166
|
+
z=maskdata,
|
167
|
+
x=x,
|
168
|
+
y=y,
|
169
|
+
colorscale="gray",
|
170
|
+
hoverongaps=False,
|
171
|
+
showscale=False,
|
172
|
+
opacity=0.4,
|
173
|
+
)
|
174
|
+
)
|
175
|
+
fig.update_layout(
|
176
|
+
xaxis=dict(showline=True, mirror=True),
|
177
|
+
yaxis=dict(showline=True, mirror=True),
|
178
|
+
title_text=title,
|
179
|
+
)
|
180
|
+
fig.update_xaxes(title="Ensembles")
|
181
|
+
fig.update_yaxes(title="Depth Cells")
|
182
|
+
st.plotly_chart(fig)
|
183
|
+
|
184
|
+
|
185
|
+
def fillselect_plotly(data, title="data", colorscale="balance"):
|
186
|
+
fig = FigureResampler(go.Figure())
|
187
|
+
data = np.int32(data)
|
188
|
+
data1 = np.where(data == -32768, None, data)
|
189
|
+
fig.add_trace(
|
190
|
+
go.Heatmap(
|
191
|
+
z=data1,
|
192
|
+
x=x,
|
193
|
+
y=y,
|
194
|
+
colorscale=colorscale,
|
195
|
+
hoverongaps=False,
|
196
|
+
)
|
197
|
+
)
|
198
|
+
# fig.add_trace(
|
199
|
+
# go.Scatter(x=X, y=Y, marker=dict(color="black", size=16), mode="lines+markers")
|
200
|
+
# )
|
201
|
+
fig.update_layout(
|
202
|
+
xaxis=dict(showline=True, mirror=True),
|
203
|
+
yaxis=dict(showline=True, mirror=True),
|
204
|
+
title_text=title,
|
205
|
+
)
|
206
|
+
fig.update_xaxes(title="Ensembles")
|
207
|
+
fig.update_yaxes(title="Depth Cells")
|
208
|
+
fig.update_layout(clickmode="event+select")
|
209
|
+
event = st.plotly_chart(fig, key="1", on_select="rerun", selection_mode="box")
|
210
|
+
|
211
|
+
return event
|
212
|
+
|
213
|
+
|
214
|
+
@st.cache_data
|
215
|
+
def trim_ends(start_ens=0, end_ens=0, ens_range=20):
|
216
|
+
depth = vdata["Depth of Transducer"] / 10
|
217
|
+
fig = make_subplots(
|
218
|
+
rows=1,
|
219
|
+
cols=2,
|
220
|
+
subplot_titles=[
|
221
|
+
"Deployment Ensemble",
|
222
|
+
"Recovery Ensemble",
|
223
|
+
],
|
224
|
+
)
|
225
|
+
fig.add_trace(
|
226
|
+
go.Scatter(
|
227
|
+
x=x[0:ens_range],
|
228
|
+
y=depth[0:ens_range],
|
229
|
+
name="Deployment",
|
230
|
+
mode="markers",
|
231
|
+
marker=dict(color="#1f77b4"),
|
232
|
+
),
|
233
|
+
row=1,
|
234
|
+
col=1,
|
235
|
+
)
|
236
|
+
|
237
|
+
fig.add_trace(
|
238
|
+
go.Scatter(
|
239
|
+
x=x[-1 * ens_range :],
|
240
|
+
y=depth[-1 * ens_range :],
|
241
|
+
name="Recovery",
|
242
|
+
mode="markers",
|
243
|
+
marker=dict(color="#17becf"),
|
244
|
+
),
|
245
|
+
row=1,
|
246
|
+
col=2,
|
247
|
+
)
|
248
|
+
|
249
|
+
if start_ens > x[0]:
|
250
|
+
fig.add_trace(
|
251
|
+
go.Scatter(
|
252
|
+
x=x[0:start_ens],
|
253
|
+
y=depth[0:start_ens],
|
254
|
+
name="Selected Points (D)",
|
255
|
+
mode="markers",
|
256
|
+
marker=dict(color="red"),
|
257
|
+
),
|
258
|
+
row=1,
|
259
|
+
col=1,
|
260
|
+
)
|
261
|
+
|
262
|
+
if end_ens < x[-1] + 1:
|
263
|
+
fig.add_trace(
|
264
|
+
go.Scatter(
|
265
|
+
x=x[end_ens : x[-1] + 1],
|
266
|
+
y=depth[end_ens : x[-1] + 1],
|
267
|
+
name="Selected Points (R)",
|
268
|
+
mode="markers",
|
269
|
+
marker=dict(color="orange"),
|
270
|
+
),
|
271
|
+
row=1,
|
272
|
+
col=2,
|
273
|
+
)
|
274
|
+
|
275
|
+
fig.update_layout(height=600, width=800, title_text="Transducer depth")
|
276
|
+
fig.update_xaxes(title="Ensembles")
|
277
|
+
fig.update_yaxes(title="Depth (m)")
|
278
|
+
st.plotly_chart(fig)
|
279
|
+
|
280
|
+
|
281
|
+
# Trim-end functions
|
282
|
+
def set_button_trimends():
|
283
|
+
# Trim ends only modifies Mask
|
284
|
+
mask = st.session_state.profile_mask_default
|
285
|
+
if st.session_state.start_ens_PT > 0:
|
286
|
+
mask[:, : st.session_state.start_ens_PT] = 1
|
287
|
+
|
288
|
+
if st.session_state.end_ens_PT <= x[-1]:
|
289
|
+
mask[:, st.session_state.end_ens_PT :] = 1
|
290
|
+
|
291
|
+
st.session_state.profile_mask_trimends = np.copy(mask)
|
292
|
+
st.session_state.profile_mask_temp = np.copy(mask)
|
293
|
+
st.session_state.isTrimEndsCheck_PT = True
|
294
|
+
|
295
|
+
|
296
|
+
def reset_button_trimends():
|
297
|
+
# Trim ends only modifies Mask
|
298
|
+
st.session_state.isTrimEndsCheck_PT = False
|
299
|
+
st.session_state.profile_mask_trimends = st.session_state.profile_mask_default
|
300
|
+
st.session_state.profile_mask_temp = st.session_state.profile_mask_default
|
301
|
+
|
302
|
+
|
303
|
+
# Side-lobe functions
|
304
|
+
def set_button_apply_sidelobe():
|
305
|
+
inmask = np.copy(st.session_state.profile_mask_temp)
|
306
|
+
transdepth = st.session_state.depth
|
307
|
+
water_column_depth = st.session_state.water_depth_PT
|
308
|
+
extra_cells = st.session_state.extra_cell_PT
|
309
|
+
mask = side_lobe_beam_angle(
|
310
|
+
transdepth,
|
311
|
+
inmask,
|
312
|
+
orientation=orientation,
|
313
|
+
water_column_depth=water_column_depth,
|
314
|
+
extra_cells=extra_cells,
|
315
|
+
cells=cells,
|
316
|
+
cell_size=cell_size,
|
317
|
+
bin1dist=bin1dist,
|
318
|
+
beam_angle=beam_angle,
|
319
|
+
)
|
320
|
+
st.session_state.sidelobe_displaymask = np.copy(mask)
|
321
|
+
|
322
|
+
|
323
|
+
def set_button_sidelobe():
|
324
|
+
st.session_state.isCutBinSideLobeCheck_PT = True
|
325
|
+
st.session_state.profile_mask_temp = np.copy(st.session_state.sidelobe_displaymask)
|
326
|
+
st.session_state.profile_mask_sidelobe = np.copy(st.session_state.profile_mask_temp)
|
327
|
+
|
328
|
+
|
329
|
+
def reset_button_sidelobe():
|
330
|
+
st.session_state.isCutBinSideLobeCheck_PT = False
|
331
|
+
if st.session_state.isTrimEndsCheck_PT:
|
332
|
+
st.session_state.profile_mask_temp = st.session_state.profile_mask_trimends
|
333
|
+
else:
|
334
|
+
st.session_state.profile_mask_temp = st.session_state.profile_mask_default
|
335
|
+
|
336
|
+
st.session_state.profile_mask_sidelobe = np.copy(st.session_state.profile_mask_temp)
|
337
|
+
st.session_state.sidelobe_displaymask = np.copy(st.session_state.profile_mask_temp)
|
338
|
+
|
339
|
+
|
340
|
+
# Cutbins Manual Functions
|
341
|
+
def set_button_apply_mask_region():
|
342
|
+
mask = np.copy(st.session_state.profile_mask_temp)
|
343
|
+
|
344
|
+
min_cell = st.session_state.profile_min_cell
|
345
|
+
max_cell = st.session_state.profile_max_cell
|
346
|
+
min_ensemble = st.session_state.profile_min_ensemble
|
347
|
+
max_ensemble = st.session_state.profile_max_ensemble
|
348
|
+
|
349
|
+
mask = manual_cut_bins(mask, min_cell, max_cell, min_ensemble, max_ensemble)
|
350
|
+
st.session_state.manual_displaymask = np.copy(mask)
|
351
|
+
st.session_state.profile_mask_temp = np.copy(mask)
|
352
|
+
st.session_state.profile_mask_manual = np.copy(mask)
|
353
|
+
|
354
|
+
st.session_state.isCutBinManualCheck_PT = True
|
355
|
+
|
356
|
+
|
357
|
+
def set_button_mask_region():
|
358
|
+
st.session_state.isCutBinManualCheck_PT = True
|
359
|
+
st.session_state.profile_mask_manual = np.copy(st.session_state.profile_mask_temp)
|
360
|
+
|
361
|
+
|
362
|
+
def set_button_delete_cell():
|
363
|
+
cell = st.session_state.profile_delete_cell
|
364
|
+
mask = st.session_state.profile_mask_temp
|
365
|
+
mask[cell, :] = 1 # Mask the entire row for the selected cell
|
366
|
+
st.session_state.profile_mask_temp = np.copy(mask)
|
367
|
+
st.session_state.profile_mask_manual = np.copy(mask)
|
368
|
+
|
369
|
+
st.session_state.isCutBinManualCheck_PT = True
|
370
|
+
|
371
|
+
|
372
|
+
def set_button_delete_ensemble():
|
373
|
+
ensemble = st.session_state.profile_delete_ensemble
|
374
|
+
mask = st.session_state.profile_mask_temp
|
375
|
+
mask[:, ensemble - 1] = 1 # Mask the entire column for the selected ensemble
|
376
|
+
st.session_state.profile_mask_temp = np.copy(mask)
|
377
|
+
st.session_state.profile_mask_manual = np.copy(mask)
|
378
|
+
st.session_state.isCutBinManualCheck_PT = True
|
379
|
+
|
380
|
+
|
381
|
+
def reset_button_mask_manual():
|
382
|
+
st.session_state.isCutBinManualCheck_PT = False
|
383
|
+
# st.session_state.isCutBinManualOn = False
|
384
|
+
|
385
|
+
if st.session_state.isCutBinSideLobeCheck_PT:
|
386
|
+
st.session_state.profile_mask_temp = st.session_state.profile_mask_sidelobe
|
387
|
+
elif st.session_state.isTrimEndsCheck_PT:
|
388
|
+
st.session_state.profile_mask_temp = st.session_state.profile_mask_trimends
|
389
|
+
else:
|
390
|
+
st.session_state.profile_mask_temp = st.session_state.profile_mask_default
|
391
|
+
|
392
|
+
# Copy to local mask
|
393
|
+
st.session_state.profile_mask_manual = np.copy(st.session_state.profile_mask_temp)
|
394
|
+
|
395
|
+
|
396
|
+
# Regrid functions
|
397
|
+
def reset_button_regrid():
|
398
|
+
st.session_state.isRegridCheck_PT = False
|
399
|
+
|
400
|
+
# Reset to previous state
|
401
|
+
if st.session_state.isCutBinManualCheck_PT:
|
402
|
+
st.session_state.profile_mask_temp = st.session_state.profile_mask_manual
|
403
|
+
elif st.session_state.isCutBinSideLobeCheck_PT:
|
404
|
+
st.session_state.profile_mask_temp = st.session_state.profile_mask_sidelobe
|
405
|
+
elif st.session_state.isTrimEndsCheck_PT:
|
406
|
+
st.session_state.profile_mask_temp = st.session_state.profile_mask_trimends
|
407
|
+
else:
|
408
|
+
st.session_state.profile_mask_temp = st.session_state.profile_mask_default
|
409
|
+
|
410
|
+
# Copy to local mask
|
411
|
+
st.session_state.profile_mask_regrid = np.copy(st.session_state.profile_mask_temp)
|
412
|
+
|
413
|
+
# Reset Data
|
414
|
+
if st.session_state.isVelocityModifiedSound_ST:
|
415
|
+
st.session_state.velocity_regrid = np.copy(st.session_state.velocity_sensor)
|
416
|
+
else:
|
417
|
+
st.session_state.velocity_regrid = np.copy(st.session_state.velocity)
|
418
|
+
st.session_state.echo_regrid = np.copy(st.session_state.echo)
|
419
|
+
st.session_state.velocity_regrid = np.copy(st.session_state.velocity)
|
420
|
+
st.session_state.correlation_regrid = np.copy(st.session_state.correlation)
|
421
|
+
st.session_state.pgood_regrid = np.copy(st.session_state.pgood)
|
422
|
+
|
423
|
+
|
424
|
+
def save_profiletest():
|
425
|
+
if st.session_state.isRegridCheck_PT:
|
426
|
+
st.session_state.profile_mask = st.session_state.profile_mask_regrid
|
427
|
+
else:
|
428
|
+
st.session_state.profile_mask = st.session_state.profile_mask_temp
|
429
|
+
# st.session_state.velocity_regrid = np.copy(st.session_state.velocity_temp)
|
430
|
+
st.session_state.isProfileTest = True
|
431
|
+
st.session_state.isVelocityTest = False
|
432
|
+
|
433
|
+
st.session_state.isSensorPageReturn = True
|
434
|
+
st.session_state.isQCPageReturn = True
|
435
|
+
|
436
|
+
|
437
|
+
# Giving infromations and warnings according to the state of masks.
|
438
|
+
if st.session_state.isQCTest or st.session_state.isSensorTest:
|
439
|
+
st.write(":grey[Working on a saved mask file ...]")
|
440
|
+
if st.session_state.isProfilePageReturn:
|
441
|
+
st.write(
|
442
|
+
":orange[Warning: Profile test already completed. Reset to change settings.]"
|
443
|
+
)
|
444
|
+
reset_selectbox = st.selectbox(
|
445
|
+
"Choose reset option",
|
446
|
+
("Sensor Test", "QC Test", "Default"),
|
447
|
+
index=None,
|
448
|
+
placeholder="Reset mask to ...",
|
449
|
+
)
|
450
|
+
# Selecting the original mask file.
|
451
|
+
if reset_selectbox == "Default":
|
452
|
+
st.write("Default mask file selected")
|
453
|
+
elif reset_selectbox == "Sensor Test":
|
454
|
+
st.write("Sensor Test mask file selected")
|
455
|
+
elif reset_selectbox == "QC Test":
|
456
|
+
st.write("QC Test mask file selected")
|
457
|
+
if reset_selectbox is not None:
|
458
|
+
hard_reset(reset_selectbox)
|
459
|
+
elif st.session_state.isFirstProfileVisit:
|
460
|
+
reset_profiletest()
|
461
|
+
st.session_state.isFirstProfileVisit = False
|
462
|
+
else:
|
463
|
+
if st.session_state.isFirstProfileVisit:
|
464
|
+
reset_profiletest()
|
465
|
+
st.session_state.isFirstProfileVisit = False
|
466
|
+
st.write(":orange[Creating a new mask file ...]")
|
467
|
+
|
468
|
+
st.header("Profile Test")
|
469
|
+
# Creating tabs for each actions
|
470
|
+
tab1, tab2, tab3, tab4, tab5 = st.tabs(
|
471
|
+
[
|
472
|
+
"Trim Ends",
|
473
|
+
"Cut Bins - Sidelobe",
|
474
|
+
"Cut Bins - Manual",
|
475
|
+
"Regriding",
|
476
|
+
"Save & Reset",
|
477
|
+
]
|
478
|
+
)
|
479
|
+
|
480
|
+
|
481
|
+
############## TRIM ENDS #################
|
482
|
+
with tab1:
|
483
|
+
st.header("Trim Ends", divider="blue")
|
484
|
+
x1 = np.arange(0, ensembles, 1)
|
485
|
+
st.session_state.ens_range = st.number_input("Change range", x[0], x[-1], 20)
|
486
|
+
st.session_state.start_ens = st.slider(
|
487
|
+
"Deployment Ensembles", 0, st.session_state.ens_range, 0
|
488
|
+
)
|
489
|
+
st.session_state.end_ens = st.slider(
|
490
|
+
"Recovery Ensembles",
|
491
|
+
x1[-1] - st.session_state.ens_range,
|
492
|
+
x1[-1] + 1,
|
493
|
+
x1[-1] + 1,
|
494
|
+
)
|
495
|
+
|
496
|
+
if st.session_state.start_ens or st.session_state.end_ens:
|
497
|
+
trim_ends(
|
498
|
+
start_ens=int(st.session_state.start_ens),
|
499
|
+
end_ens=int(st.session_state.end_ens),
|
500
|
+
ens_range=int(st.session_state.ens_range),
|
501
|
+
)
|
502
|
+
|
503
|
+
st.session_state.start_ens_PT = st.session_state.start_ens
|
504
|
+
st.session_state.end_ens_PT = st.session_state.end_ens
|
505
|
+
st.session_state.trimends_endpoints = np.array(
|
506
|
+
[st.session_state.start_ens_PT, st.session_state.end_ens_PT]
|
507
|
+
)
|
508
|
+
|
509
|
+
left_te, right_te = st.columns([1, 1])
|
510
|
+
with left_te:
|
511
|
+
trimends_mask_button = st.button("Trim Ends", on_click=set_button_trimends)
|
512
|
+
|
513
|
+
# Display output
|
514
|
+
if trimends_mask_button:
|
515
|
+
st.success("Mask data updated")
|
516
|
+
st.write("Trim End Points", st.session_state.trimends_endpoints)
|
517
|
+
else:
|
518
|
+
st.write(":red[mask data not updated]")
|
519
|
+
|
520
|
+
with right_te:
|
521
|
+
trimends_reset_button = st.button(
|
522
|
+
"Reset Trim Ends", on_click=reset_button_trimends
|
523
|
+
)
|
524
|
+
if trimends_reset_button:
|
525
|
+
st.success("Mask data reset to default.")
|
526
|
+
|
527
|
+
|
528
|
+
############ CUT BINS (SIDE LOBE) ############################
|
529
|
+
with tab2:
|
530
|
+
st.header("Cut Bins: Side Lobe Contamination", divider="blue")
|
531
|
+
st.write(
|
532
|
+
"""
|
533
|
+
The side lobe echos from hard surface such as sea surface or bottom of the ocean can contaminate
|
534
|
+
data closer to this region. The data closer to the surface or bottom can be removed using
|
535
|
+
the relation between beam angle and the thickness of the contaminated layer.
|
536
|
+
"""
|
537
|
+
)
|
538
|
+
|
539
|
+
left1, right1 = st.columns([1, 1])
|
540
|
+
|
541
|
+
with left1:
|
542
|
+
orientation = st.session_state.beam_direction_QCT
|
543
|
+
st.write(f"The orientation is `{orientation}`.")
|
544
|
+
beam = st.radio("Select beam", (1, 2, 3, 4), horizontal=True)
|
545
|
+
beam = beam - 1
|
546
|
+
st.session_state.beam = beam
|
547
|
+
|
548
|
+
with right1:
|
549
|
+
st.session_state.water_depth_PT = 0
|
550
|
+
|
551
|
+
st.session_state.extra_cell_PT = st.number_input(
|
552
|
+
"Additional Cells to Delete", 0, 10, 0
|
553
|
+
)
|
554
|
+
if orientation.lower() == "down":
|
555
|
+
water_column_depth = st.number_input(
|
556
|
+
"Enter water column depth (m): ", 0, 15000, 0
|
557
|
+
)
|
558
|
+
side_lobe_button = st.button(
|
559
|
+
label="Cut bins", on_click=set_button_apply_sidelobe
|
560
|
+
)
|
561
|
+
|
562
|
+
left2, right2 = st.columns([1, 1])
|
563
|
+
|
564
|
+
with left2:
|
565
|
+
# if st.session_state.isCutBinSideLobeCheck_PT:
|
566
|
+
# fillplot_plotly(
|
567
|
+
# echo[beam, :, :],
|
568
|
+
# title="Echo Intensity (Masked)",
|
569
|
+
# maskdata=st.session_state.profile_mask_temp,
|
570
|
+
# )
|
571
|
+
# else:
|
572
|
+
fillplot_plotly(
|
573
|
+
echo[beam, :, :],
|
574
|
+
maskdata=st.session_state.sidelobe_displaymask,
|
575
|
+
title="Echo Intensity",
|
576
|
+
)
|
577
|
+
|
578
|
+
with right2:
|
579
|
+
fillplot_plotly(
|
580
|
+
st.session_state.sidelobe_displaymask,
|
581
|
+
colorscale="greys",
|
582
|
+
title="Mask Data ",
|
583
|
+
)
|
584
|
+
|
585
|
+
left3sl, right3sl = st.columns([1, 1])
|
586
|
+
with left3sl:
|
587
|
+
update_mask_cutbin_button = st.button(
|
588
|
+
"Update Mask (Side Lobe)", on_click=set_button_sidelobe
|
589
|
+
)
|
590
|
+
if update_mask_cutbin_button:
|
591
|
+
st.success("Mask file updated")
|
592
|
+
|
593
|
+
with right3sl:
|
594
|
+
reset_mask_cutbin_button = st.button(
|
595
|
+
"Reset Mask (Side lobe)", on_click=reset_button_sidelobe
|
596
|
+
)
|
597
|
+
if reset_mask_cutbin_button:
|
598
|
+
st.info("Mask File Reset (Side Lobe)")
|
599
|
+
|
600
|
+
if not update_mask_cutbin_button:
|
601
|
+
st.write(":red[mask file not updated]")
|
602
|
+
|
603
|
+
|
604
|
+
########### CUT BINS: Manual #################
|
605
|
+
with tab3:
|
606
|
+
st.header("Cut Bins: Manual", divider="blue")
|
607
|
+
|
608
|
+
left3, right3 = st.columns([1, 2])
|
609
|
+
with left3:
|
610
|
+
# User selects beam (1-4)
|
611
|
+
beam = st.radio(
|
612
|
+
"Select beam", (1, 2, 3, 4), horizontal=True, key="beam_selection"
|
613
|
+
)
|
614
|
+
beam_index = beam - 1
|
615
|
+
st.subheader("Mask Selected Regions")
|
616
|
+
# with st.form(key="manual_cutbin_form"):
|
617
|
+
st.write("Select the specific range of cells and ensembles to delete")
|
618
|
+
|
619
|
+
# Input for selecting minimum and maximum cells
|
620
|
+
st.session_state.profile_min_cell = st.number_input(
|
621
|
+
"Min Cell", 0, int(flobj.field()["Cells"]), 0
|
622
|
+
)
|
623
|
+
st.session_state.profile_max_cell = st.number_input(
|
624
|
+
"Max Cell", 0, int(flobj.field()["Cells"]), int(flobj.field()["Cells"])
|
625
|
+
)
|
626
|
+
|
627
|
+
st.write(st.session_state.profile_max_cell)
|
628
|
+
# Input for selecting minimum and maximum ensembles
|
629
|
+
st.session_state.profile_min_ensemble = st.number_input(
|
630
|
+
"Min Ensemble", 0, int(flobj.ensembles), 0
|
631
|
+
)
|
632
|
+
st.session_state.profile_max_ensemble = st.number_input(
|
633
|
+
"Max Ensemble", 0, int(flobj.ensembles), int(flobj.ensembles)
|
634
|
+
)
|
635
|
+
|
636
|
+
# Submit button to apply the mask
|
637
|
+
cut_bins_mask_manual = st.button(label="Apply Manual Cut Bins")
|
638
|
+
if cut_bins_mask_manual:
|
639
|
+
set_button_apply_mask_region()
|
640
|
+
|
641
|
+
# Adding the new feature: Delete Single Cell or Ensemble
|
642
|
+
st.subheader("Delete Specific Cell or Ensemble")
|
643
|
+
|
644
|
+
# Step 1: User chooses between deleting a cell or an ensemble
|
645
|
+
delete_option = st.radio(
|
646
|
+
"Select option to delete", ("Cell", "Ensemble"), horizontal=True
|
647
|
+
)
|
648
|
+
|
649
|
+
# Step 2: Display options based on user's choice
|
650
|
+
if delete_option == "Cell":
|
651
|
+
# Option to delete a specific cell across all ensembles
|
652
|
+
st.write("Select a specific cell to delete across all ensembles")
|
653
|
+
|
654
|
+
# Input for selecting a single cell
|
655
|
+
st.session_state.profile_delete_cell = st.number_input(
|
656
|
+
"Cell", 0, int(flobj.field()["Cells"]), 0, key="single_cell"
|
657
|
+
)
|
658
|
+
|
659
|
+
# Submit button to apply the mask for cell deletion
|
660
|
+
delete_cell_button = st.button(
|
661
|
+
label="Delete Cell", on_click=set_button_delete_cell
|
662
|
+
)
|
663
|
+
|
664
|
+
if delete_cell_button:
|
665
|
+
st.write("Deleted cell: ", st.session_state.profile_delete_cell)
|
666
|
+
|
667
|
+
if delete_option == "Ensemble":
|
668
|
+
# Option to delete a specific ensemble across all cells
|
669
|
+
st.write("Select a specific ensemble to delete across all cells")
|
670
|
+
|
671
|
+
# Input for selecting a specific ensemble
|
672
|
+
st.session_state.profile_delete_ensemble = st.number_input(
|
673
|
+
"Ensemble", 0, int(flobj.ensembles), 0, key="single_ensemble"
|
674
|
+
)
|
675
|
+
|
676
|
+
# Submit button to apply the mask for ensemble deletion
|
677
|
+
delete_ensemble_button = st.button(
|
678
|
+
label="Delete Ensemble", on_click=set_button_delete_ensemble
|
679
|
+
)
|
680
|
+
|
681
|
+
if delete_ensemble_button:
|
682
|
+
st.write("Deleted Ensemble: ", st.session_state.profile_delete_ensemble)
|
683
|
+
|
684
|
+
velocity = st.session_state.velocity_temp
|
685
|
+
# Map variable selection to corresponding data
|
686
|
+
data_dict = {
|
687
|
+
"Velocity": velocity,
|
688
|
+
"Echo Intensity": echo,
|
689
|
+
"Correlation": correlation,
|
690
|
+
"Percentage Good": pgood,
|
691
|
+
}
|
692
|
+
|
693
|
+
with right3:
|
694
|
+
# Selection of variable (Velocity, Echo Intensity, etc.)
|
695
|
+
variable = st.selectbox(
|
696
|
+
"Select Variable to Display",
|
697
|
+
("Velocity", "Echo Intensity", "Correlation", "Percentage Good"),
|
698
|
+
)
|
699
|
+
# Display the selected variable and beam
|
700
|
+
selected_data = data_dict[variable][beam_index, :, :]
|
701
|
+
fillplot_plotly(
|
702
|
+
selected_data,
|
703
|
+
title=variable + "(Masked Manually)",
|
704
|
+
maskdata=st.session_state.profile_mask_temp,
|
705
|
+
)
|
706
|
+
# else:
|
707
|
+
# fillplot_plotly(selected_data, title=f"{variable}")
|
708
|
+
fillplot_plotly(
|
709
|
+
st.session_state.profile_mask_temp,
|
710
|
+
colorscale="greys",
|
711
|
+
title="Mask Data",
|
712
|
+
)
|
713
|
+
|
714
|
+
# Layout with two columns
|
715
|
+
col1, col2 = st.columns([1, 3])
|
716
|
+
|
717
|
+
# Button to reset the mask data, with unique key
|
718
|
+
reset_mask_button = st.button(
|
719
|
+
"Reset Cut Bins Manual",
|
720
|
+
key="reset_mask_button",
|
721
|
+
on_click=reset_button_mask_manual,
|
722
|
+
)
|
723
|
+
if reset_mask_button:
|
724
|
+
st.info("Cut Bins Manual Reset. Mask data is changed to previous state.")
|
725
|
+
|
726
|
+
############ REGRID ###########################################
|
727
|
+
with tab4:
|
728
|
+
st.header("Regrid Depth Cells", divider="blue")
|
729
|
+
|
730
|
+
st.write(
|
731
|
+
"""
|
732
|
+
When the ADCP buoy has vertical oscillations (greater than depth cell size),
|
733
|
+
the depth bins has to be regridded based on the pressure sensor data. The data
|
734
|
+
can be regrided either till the surface or till the last bin.
|
735
|
+
If the `Cell` option is selected, ensure that the end data are trimmed.
|
736
|
+
Manual option permits choosing the end cell depth.
|
737
|
+
"""
|
738
|
+
)
|
739
|
+
|
740
|
+
left4, right4 = st.columns([1, 3])
|
741
|
+
|
742
|
+
with left4:
|
743
|
+
if st.session_state.beam_direction_QCT.lower() == "up":
|
744
|
+
end_cell_option = st.radio(
|
745
|
+
"Select the depth of last bin for regridding",
|
746
|
+
("Cell", "Surface", "Manual"),
|
747
|
+
horizontal=True,
|
748
|
+
)
|
749
|
+
else:
|
750
|
+
end_cell_option = st.radio(
|
751
|
+
"Select the depth of last bin for regridding",
|
752
|
+
("Cell", "Manual"),
|
753
|
+
horizontal=True,
|
754
|
+
)
|
755
|
+
|
756
|
+
st.session_state.end_cell_option_PT = end_cell_option
|
757
|
+
st.write(f"You have selected: `{end_cell_option}`")
|
758
|
+
|
759
|
+
if end_cell_option == "Manual":
|
760
|
+
mean_depth = (
|
761
|
+
np.mean(st.session_state.vlead.vleader["Depth of Transducer"]) / 10
|
762
|
+
)
|
763
|
+
mean_depth = round(mean_depth, 2)
|
764
|
+
|
765
|
+
st.write(
|
766
|
+
f"The transducer depth is {mean_depth} m. The value should not exceed the transducer depth"
|
767
|
+
)
|
768
|
+
if st.session_state.beam_direction_QCT.lower() == "up":
|
769
|
+
boundary = st.number_input(
|
770
|
+
"Enter the depth (m):", max_value=int(mean_depth), min_value=0
|
771
|
+
)
|
772
|
+
else:
|
773
|
+
boundary = st.number_input(
|
774
|
+
"Enter the depth (m):", min_value=int(mean_depth)
|
775
|
+
)
|
776
|
+
else:
|
777
|
+
boundary = 0
|
778
|
+
|
779
|
+
st.session_state.interpolate_PT = st.radio(
|
780
|
+
"Choose interpolation method:", ("nearest", "linear", "cubic")
|
781
|
+
)
|
782
|
+
st.session_state.manualdepth_PT = boundary
|
783
|
+
|
784
|
+
progress_text = "Regridding in progress. Please wait."
|
785
|
+
grid_bar = st.progress(0, text=progress_text)
|
786
|
+
|
787
|
+
regrid_button = st.button(label="Regrid Data")
|
788
|
+
if regrid_button:
|
789
|
+
transdepth = st.session_state.depth
|
790
|
+
z, st.session_state.velocity_regrid = regrid3d(
|
791
|
+
transdepth,
|
792
|
+
st.session_state.velocity_temp,
|
793
|
+
-32768,
|
794
|
+
trimends=st.session_state.trimends_endpoints,
|
795
|
+
end_cell_option=st.session_state.end_cell_option_PT,
|
796
|
+
orientation=st.session_state.beam_direction_QCT,
|
797
|
+
method=st.session_state.interpolate_PT,
|
798
|
+
boundary_limit=boundary,
|
799
|
+
cells=cells,
|
800
|
+
cell_size=cell_size,
|
801
|
+
bin1dist=bin1dist,
|
802
|
+
beams=beams,
|
803
|
+
)
|
804
|
+
grid_bar.progress(20, text=progress_text)
|
805
|
+
st.write(":grey[Regrided velocity ...]")
|
806
|
+
z, st.session_state.echo_regrid = regrid3d(
|
807
|
+
transdepth,
|
808
|
+
echo,
|
809
|
+
-32768,
|
810
|
+
trimends=st.session_state.trimends_endpoints,
|
811
|
+
end_cell_option=st.session_state.end_cell_option_PT,
|
812
|
+
orientation=st.session_state.beam_direction_QCT,
|
813
|
+
method=st.session_state.interpolate_PT,
|
814
|
+
boundary_limit=boundary,
|
815
|
+
cells=cells,
|
816
|
+
cell_size=cell_size,
|
817
|
+
bin1dist=bin1dist,
|
818
|
+
beams=beams,
|
819
|
+
)
|
820
|
+
grid_bar.progress(40, text=progress_text)
|
821
|
+
st.write(":grey[Regrided echo intensity ...]")
|
822
|
+
z, st.session_state.correlation_regrid = regrid3d(
|
823
|
+
transdepth,
|
824
|
+
correlation,
|
825
|
+
-32768,
|
826
|
+
trimends=st.session_state.trimends_endpoints,
|
827
|
+
end_cell_option=st.session_state.end_cell_option_PT,
|
828
|
+
orientation=st.session_state.beam_direction_QCT,
|
829
|
+
method=st.session_state.interpolate_PT,
|
830
|
+
boundary_limit=boundary,
|
831
|
+
cells=cells,
|
832
|
+
cell_size=cell_size,
|
833
|
+
bin1dist=bin1dist,
|
834
|
+
beams=beams,
|
835
|
+
)
|
836
|
+
grid_bar.progress(60, text=progress_text)
|
837
|
+
st.write(":grey[Regrided correlation...]")
|
838
|
+
z, st.session_state.pgood_regrid = regrid3d(
|
839
|
+
transdepth,
|
840
|
+
pgood,
|
841
|
+
-32768,
|
842
|
+
trimends=st.session_state.trimends_endpoints,
|
843
|
+
end_cell_option=st.session_state.end_cell_option_PT,
|
844
|
+
orientation=st.session_state.beam_direction_QCT,
|
845
|
+
method=st.session_state.interpolate_PT,
|
846
|
+
boundary_limit=boundary,
|
847
|
+
cells=cells,
|
848
|
+
cell_size=cell_size,
|
849
|
+
bin1dist=bin1dist,
|
850
|
+
beams=beams,
|
851
|
+
)
|
852
|
+
grid_bar.progress(80, text=progress_text)
|
853
|
+
st.write(":grey[Regrided percent good...]")
|
854
|
+
|
855
|
+
z, st.session_state.profile_mask_regrid = regrid2d(
|
856
|
+
transdepth,
|
857
|
+
st.session_state.profile_mask_temp,
|
858
|
+
1,
|
859
|
+
trimends=st.session_state.trimends_endpoints,
|
860
|
+
end_cell_option=st.session_state.end_cell_option_PT,
|
861
|
+
orientation=st.session_state.beam_direction_QCT,
|
862
|
+
method="nearest",
|
863
|
+
boundary_limit=boundary,
|
864
|
+
cells=cells,
|
865
|
+
cell_size=cell_size,
|
866
|
+
bin1dist=bin1dist,
|
867
|
+
)
|
868
|
+
|
869
|
+
grid_bar.progress(99, text=progress_text)
|
870
|
+
st.write(":grey[Regrided mask...]")
|
871
|
+
|
872
|
+
st.session_state.depth_axis = z
|
873
|
+
st.write(":grey[New depth axis created...]")
|
874
|
+
|
875
|
+
grid_bar.progress(100, text="Completed")
|
876
|
+
st.write(":green[All data regrided!]")
|
877
|
+
|
878
|
+
st.write(
|
879
|
+
"No. of grid depth bins before regridding: ", np.shape(velocity)[1]
|
880
|
+
)
|
881
|
+
st.write(
|
882
|
+
"No. of grid depth bins after regridding: ",
|
883
|
+
np.shape(st.session_state.velocity_regrid)[1],
|
884
|
+
)
|
885
|
+
st.session_state.isRegridCheck_PT = True
|
886
|
+
|
887
|
+
regrid_reset_button = st.button(
|
888
|
+
"Reset Regrid Test", on_click=reset_button_regrid
|
889
|
+
)
|
890
|
+
|
891
|
+
if regrid_reset_button:
|
892
|
+
st.info("Data Reset")
|
893
|
+
|
894
|
+
with right4:
|
895
|
+
if st.session_state.isRegridCheck_PT:
|
896
|
+
fillplot_plotly(
|
897
|
+
st.session_state.velocity_regrid[0, :, :],
|
898
|
+
title="Regridded Velocity File",
|
899
|
+
maskdata=st.session_state.profile_mask_regrid,
|
900
|
+
)
|
901
|
+
fillplot_plotly(
|
902
|
+
st.session_state.profile_mask_regrid,
|
903
|
+
colorscale="greys",
|
904
|
+
title="Regridded Mask File",
|
905
|
+
)
|
906
|
+
else:
|
907
|
+
fillplot_plotly(
|
908
|
+
velocity[0, :, :],
|
909
|
+
maskdata=st.session_state.profile_mask_temp,
|
910
|
+
title="Original File",
|
911
|
+
)
|
912
|
+
|
913
|
+
|
914
|
+
########### Save and Reset Mask ##############
|
915
|
+
with tab5:
|
916
|
+
st.header("Save & Reset Mask Data", divider="blue")
|
917
|
+
|
918
|
+
col1, col2 = st.columns([1, 1])
|
919
|
+
with col1:
|
920
|
+
save_mask_button = st.button(label="Save Mask Data", on_click=save_profiletest)
|
921
|
+
if save_mask_button:
|
922
|
+
st.success("Mask data saved")
|
923
|
+
# Table summarizing changes
|
924
|
+
changes_summary = pd.DataFrame(
|
925
|
+
[
|
926
|
+
[
|
927
|
+
"Trim Ends",
|
928
|
+
"True" if st.session_state.isTrimEndsCheck_PT else "False",
|
929
|
+
],
|
930
|
+
[
|
931
|
+
"Cut Bins: Side Lobe Contamination",
|
932
|
+
"True"
|
933
|
+
if st.session_state.isCutBinSideLobeCheck_PT
|
934
|
+
else "False",
|
935
|
+
],
|
936
|
+
[
|
937
|
+
"Cut Bins: Manual",
|
938
|
+
"True" if st.session_state.isCutBinManualCheck_PT else "False",
|
939
|
+
],
|
940
|
+
[
|
941
|
+
"Regrid Depth Cells",
|
942
|
+
"True" if st.session_state.isRegridCheck_PT else "False",
|
943
|
+
],
|
944
|
+
],
|
945
|
+
columns=["Parameter", "Status"],
|
946
|
+
)
|
947
|
+
|
948
|
+
# Define a mapping function for styling
|
949
|
+
def status_color_map(value):
|
950
|
+
if value == "True":
|
951
|
+
return "background-color: green; color: white"
|
952
|
+
elif value == "False":
|
953
|
+
return "background-color: red; color: white"
|
954
|
+
else:
|
955
|
+
return ""
|
956
|
+
|
957
|
+
# Apply styles using Styler.apply
|
958
|
+
styled_table = changes_summary.style.set_properties(
|
959
|
+
**{"text-align": "center"}
|
960
|
+
)
|
961
|
+
styled_table = styled_table.map(status_color_map, subset=["Status"])
|
962
|
+
|
963
|
+
# Display the styled table
|
964
|
+
st.write(styled_table.to_html(), unsafe_allow_html=True)
|
965
|
+
else:
|
966
|
+
st.write(":red[Mask data not saved]")
|
967
|
+
with col2:
|
968
|
+
reset_mask_button = st.button("Reset mask data", on_click=reset_profiletest)
|
969
|
+
if reset_mask_button:
|
970
|
+
st.info("Mask data is reset to default")
|