pyadps 0.2.1b0__py3-none-any.whl → 0.3.0__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 +11 -5
- pyadps/pages/01_Read_File.py +623 -215
- pyadps/pages/02_View_Raw_Data.py +97 -41
- pyadps/pages/03_Download_Raw_File.py +200 -67
- pyadps/pages/04_Sensor_Health.py +905 -0
- pyadps/pages/05_QC_Test.py +493 -0
- pyadps/pages/06_Profile_Test.py +971 -0
- pyadps/pages/07_Velocity_Test.py +600 -0
- pyadps/pages/08_Write_File.py +623 -0
- pyadps/pages/09_Add-Ons.py +168 -0
- pyadps/utils/__init__.py +5 -3
- pyadps/utils/autoprocess.py +371 -80
- pyadps/utils/logging_utils.py +269 -0
- pyadps/utils/metadata/config.ini +22 -4
- pyadps/utils/metadata/demo.000 +0 -0
- pyadps/utils/metadata/flmeta.json +420 -420
- pyadps/utils/metadata/vlmeta.json +611 -565
- pyadps/utils/multifile.py +292 -0
- pyadps/utils/plotgen.py +505 -3
- pyadps/utils/profile_test.py +720 -125
- pyadps/utils/pyreadrdi.py +164 -92
- pyadps/utils/readrdi.py +436 -186
- pyadps/utils/script.py +197 -147
- pyadps/utils/sensor_health.py +120 -0
- pyadps/utils/signal_quality.py +472 -68
- pyadps/utils/velocity_test.py +79 -31
- pyadps/utils/writenc.py +222 -39
- {pyadps-0.2.1b0.dist-info → pyadps-0.3.0.dist-info}/METADATA +13 -14
- pyadps-0.3.0.dist-info/RECORD +35 -0
- {pyadps-0.2.1b0.dist-info → pyadps-0.3.0.dist-info}/WHEEL +1 -1
- {pyadps-0.2.1b0.dist-info → pyadps-0.3.0.dist-info}/entry_points.txt +1 -0
- pyadps/pages/04_QC_Test.py +0 -334
- pyadps/pages/05_Profile_Test.py +0 -575
- pyadps/pages/06_Velocity_Test.py +0 -341
- pyadps/pages/07_Write_File.py +0 -452
- pyadps/utils/cutbin.py +0 -413
- pyadps/utils/regrid.py +0 -279
- pyadps-0.2.1b0.dist-info/RECORD +0 -31
- {pyadps-0.2.1b0.dist-info → pyadps-0.3.0.dist-info}/LICENSE +0 -0
@@ -0,0 +1,600 @@
|
|
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.profile_test import side_lobe_beam_angle
|
10
|
+
from utils.signal_quality import default_mask
|
11
|
+
from utils.velocity_test import (
|
12
|
+
despike,
|
13
|
+
flatline, # magnetic_declination,
|
14
|
+
magdec,
|
15
|
+
velocity_cutoff,
|
16
|
+
wmm2020api,
|
17
|
+
velocity_modifier,
|
18
|
+
)
|
19
|
+
|
20
|
+
if "flead" not in st.session_state:
|
21
|
+
st.write(":red[Please Select Data!]")
|
22
|
+
st.stop()
|
23
|
+
|
24
|
+
flobj = st.session_state.flead
|
25
|
+
vlobj = st.session_state.vlead
|
26
|
+
fdata = flobj.fleader
|
27
|
+
vdata = vlobj.vleader
|
28
|
+
|
29
|
+
|
30
|
+
def reset_velocitytest():
|
31
|
+
# Reset Global Test
|
32
|
+
st.session_state.isVelocityTest = False
|
33
|
+
|
34
|
+
# Reset Local Tests
|
35
|
+
st.session_state.isMagnetCheck_VT = False
|
36
|
+
st.session_state.isDespikeCheck_VT = False
|
37
|
+
st.session_state.isFlatlineCheck = False
|
38
|
+
st.session_state.isCutoffCheck_VT = False
|
39
|
+
|
40
|
+
st.session_state.isVelocityModifiedMagnet = False
|
41
|
+
|
42
|
+
# Page return
|
43
|
+
st.session_state.isProfilePageReturn = False
|
44
|
+
if not st.session_state.isProfileTest:
|
45
|
+
st.session_state.isQCPageReturn = False
|
46
|
+
if not st.session_state.isQCTest:
|
47
|
+
st.session_state.isSensorPageReturn = False
|
48
|
+
|
49
|
+
# Data Reset
|
50
|
+
if st.session_state.isRegridCheck_PT:
|
51
|
+
st.session_state.velocity_magnet = st.session_state.velocity_regrid
|
52
|
+
elif st.session_state.isVelocityModifiedSound_ST:
|
53
|
+
st.session_state.velocity_magnet = st.session_state.velocity_sensor
|
54
|
+
else:
|
55
|
+
st.session_state.velocity_magnet = st.session_state.velocity
|
56
|
+
|
57
|
+
# Reset Mask
|
58
|
+
if st.session_state.isProfileTest:
|
59
|
+
if st.session_state.isRegridCheck_PT:
|
60
|
+
st.session_state.velocity_mask_default = np.copy(
|
61
|
+
st.session_state.profile_mask_regrid
|
62
|
+
)
|
63
|
+
else:
|
64
|
+
st.session_state.velocity_mask_default = np.copy(
|
65
|
+
st.session_state.profile_mask
|
66
|
+
)
|
67
|
+
elif st.session_state.isQCTest:
|
68
|
+
st.session_state.velocity_mask_default = np.copy(st.session_state.qc_mask)
|
69
|
+
elif st.session_state.isSensorTest:
|
70
|
+
st.session_state.velocity_mask_default = np.copy(st.session_state.sensor_mask)
|
71
|
+
else:
|
72
|
+
st.session_state.velocity_mask_default = np.copy(st.session_state.orig_mask)
|
73
|
+
|
74
|
+
mask = st.session_state.velocity_mask_default
|
75
|
+
st.session_state.velocity_mask_temp = np.copy(mask)
|
76
|
+
st.session_state.velocity_mask = np.copy(mask)
|
77
|
+
st.session_state.velocity_mask_cutoff = np.copy(mask)
|
78
|
+
st.session_state.velocity_mask_spike = np.copy(mask)
|
79
|
+
st.session_state.velocity_mask_flatline = np.copy(mask)
|
80
|
+
|
81
|
+
|
82
|
+
def hard_reset(option):
|
83
|
+
# Reset Global Test
|
84
|
+
st.session_state.isVelocityTest = False
|
85
|
+
|
86
|
+
# Reset Local Tests
|
87
|
+
st.session_state.isMagnetCheck_VT = False
|
88
|
+
st.session_state.isDespikeCheck_VT = False
|
89
|
+
st.session_state.isFlatlineCheck = False
|
90
|
+
st.session_state.isCutoffCheck_VT = False
|
91
|
+
|
92
|
+
# Page return
|
93
|
+
st.session_state.isProfilePageReturn = False
|
94
|
+
if not st.session_state.isProfileTest:
|
95
|
+
st.session_state.isQCPageReturn = False
|
96
|
+
if not st.session_state.isQCTest:
|
97
|
+
st.session_state.isSensorPageReturn = False
|
98
|
+
|
99
|
+
# Velocity data reset
|
100
|
+
st.session_state.velocity_magnet = st.session_state.velocity
|
101
|
+
|
102
|
+
if option == "Sensor Test":
|
103
|
+
st.session_state.velocity_mask_default = np.copy(st.session_state.sensor_mask)
|
104
|
+
if st.session_state.isVelocityModifiedSound_ST:
|
105
|
+
st.session_state.velocity_magnet = st.session_state.velocity_sensor
|
106
|
+
elif option == "QC Test":
|
107
|
+
st.session_state.velocity_mask_default = np.copy(st.session_state.qc_mask)
|
108
|
+
elif option == "Profile Test":
|
109
|
+
st.session_state.velocity_mask_default = np.copy(st.session_state.profile_mask)
|
110
|
+
if st.session_state.isRegridCheck_PT:
|
111
|
+
st.session_state.velocity_magnet = st.session_state.velocity_regrid
|
112
|
+
else:
|
113
|
+
st.session_state.velocity_mask_default = np.copy(st.session_state.orig_mask)
|
114
|
+
|
115
|
+
st.session_state.velocity_mask = np.copy(st.session_state.velocity_mask_default)
|
116
|
+
st.session_state.velocity_mask_temp = np.copy(
|
117
|
+
st.session_state.velocity_mask_default
|
118
|
+
)
|
119
|
+
st.session_state.velocity_mask_cutoff = np.copy(
|
120
|
+
st.session_state.velocity_mask_default
|
121
|
+
)
|
122
|
+
st.session_state.velocity_mask_spike = np.copy(
|
123
|
+
st.session_state.velocity_mask_default
|
124
|
+
)
|
125
|
+
st.session_state.velocity_mask_flatline = np.copy(
|
126
|
+
st.session_state.velocity_mask_default
|
127
|
+
)
|
128
|
+
|
129
|
+
|
130
|
+
####### Initialize Mask File ##############
|
131
|
+
if (
|
132
|
+
st.session_state.isProfileTest
|
133
|
+
or st.session_state.isQCTest
|
134
|
+
or st.session_state.isSensorTest
|
135
|
+
):
|
136
|
+
st.write(":grey[Working on a saved mask file ...]")
|
137
|
+
if st.session_state.isVelocityPageReturn:
|
138
|
+
st.write(
|
139
|
+
":orange[Warning: Velocity test already completed. Reset to change settings.]"
|
140
|
+
)
|
141
|
+
reset_selectbox = st.selectbox(
|
142
|
+
"Choose reset option",
|
143
|
+
("Profile Test", "QC Test", "Sensor Test", "Default"),
|
144
|
+
index=None,
|
145
|
+
placeholder="Reset mask to ...",
|
146
|
+
)
|
147
|
+
if reset_selectbox == "Default":
|
148
|
+
st.write("Default mask file selected")
|
149
|
+
elif reset_selectbox == "Sensor Test":
|
150
|
+
st.write("Sensor Test mask file selected")
|
151
|
+
elif reset_selectbox == "QC Test":
|
152
|
+
st.write("QC Test mask file selected")
|
153
|
+
elif reset_selectbox == "Profile Test":
|
154
|
+
st.write("Profile Test mask file selected")
|
155
|
+
|
156
|
+
if reset_selectbox is not None:
|
157
|
+
hard_reset(reset_selectbox)
|
158
|
+
|
159
|
+
elif st.session_state.isFirstVelocityVisit:
|
160
|
+
reset_velocitytest()
|
161
|
+
st.session_state.isFirstVelocityVisit = False
|
162
|
+
else:
|
163
|
+
if st.session_state.isFirstVelocityVisit:
|
164
|
+
reset_velocitytest()
|
165
|
+
st.session_state.isFirstVelocityVisit = False
|
166
|
+
st.write(":grey[Creating a new mask file ...]")
|
167
|
+
|
168
|
+
|
169
|
+
# If data are not regrided use the default one
|
170
|
+
# if st.session_state.isGridSave:
|
171
|
+
# st.session_state.velocity_magnet = np.copy(st.session_state.velocity_regrid)
|
172
|
+
# else:
|
173
|
+
# st.session_state.velocity_magnet = np.copy(st.session_state.velocity)
|
174
|
+
|
175
|
+
velocity = st.session_state.velocity_magnet
|
176
|
+
|
177
|
+
ensembles = st.session_state.head.ensembles
|
178
|
+
cells = flobj.field()["Cells"]
|
179
|
+
x = np.arange(0, ensembles, 1)
|
180
|
+
y = np.arange(0, cells, 1)
|
181
|
+
|
182
|
+
|
183
|
+
########### Introduction ##########
|
184
|
+
st.header("Velocity Test", divider="orange")
|
185
|
+
|
186
|
+
st.write(
|
187
|
+
"""
|
188
|
+
The processing in this page apply only to the velocity data.
|
189
|
+
"""
|
190
|
+
)
|
191
|
+
tab1, tab2, tab3, tab4, tab5 = st.tabs(
|
192
|
+
[
|
193
|
+
"Magnetic Declination",
|
194
|
+
"Velocity Cutoffs",
|
195
|
+
"Despike Data",
|
196
|
+
"Remove Flatline",
|
197
|
+
"Save & Reset Data",
|
198
|
+
]
|
199
|
+
)
|
200
|
+
|
201
|
+
############ Magnetic Declination ##############
|
202
|
+
# Commenting the wmm2020 c based model if needed can be implemented.
|
203
|
+
|
204
|
+
# * The magnetic declination is obtained from World Magnetic Model 2020 (WMM2020).
|
205
|
+
# The python wrapper module `wmm2020` is available from this [Link](https://github.com/space-physics/wmm2020).
|
206
|
+
|
207
|
+
with tab1:
|
208
|
+
st.header("Magnetic Declination", divider="blue")
|
209
|
+
st.write(
|
210
|
+
"""
|
211
|
+
* The pygeomag method uses a python library [pygeomag](https://github.com/boxpet/pygeomag.git) for calculating the magnetic declination.
|
212
|
+
* It can work from 2010 till date.
|
213
|
+
* The API method utilizes the online magnetic declination service provided by the National Geophysical Data Center (NGDC)
|
214
|
+
of the National Oceanic and Atmospheric Administration (NOAA) to calculate the magnetic declination. The service is available at this [link](https://www.ngdc.noaa.gov/geomag/calculators/magcalc.shtml#declination).
|
215
|
+
Internet connection is necessary for this method to work.
|
216
|
+
* According to the year, different models are used for calculating magnetic declination.
|
217
|
+
* From 2025 till date, WMM2025 (World Magnetic Model)
|
218
|
+
* From 2019 to 2024 IGRF (International Geomagnetic Reference Field)
|
219
|
+
* From 2000 to 2018 EMM (Enhanced Magnetic Model)
|
220
|
+
* Before 1999 IGRF
|
221
|
+
* In the manual method, the user can directly enter the magnetic declination.
|
222
|
+
If the magnetic declination is reset, re-run the remaining tests again.
|
223
|
+
"""
|
224
|
+
)
|
225
|
+
|
226
|
+
# Selecting the method to calculate magnetic declination.
|
227
|
+
# method = st.radio("Select a method", ("WMM2020", "API", "Manual"), horizontal=True)
|
228
|
+
method = st.radio("Select a method", ("pygeomag", "API", "Manual"), horizontal=True)
|
229
|
+
# method = method - 1
|
230
|
+
st.session_state.method = method
|
231
|
+
|
232
|
+
if "isMagnetButton" not in st.session_state:
|
233
|
+
st.session_state.isMagnetButton = False
|
234
|
+
|
235
|
+
# Track button clicks
|
236
|
+
if "isButtonClicked" not in st.session_state:
|
237
|
+
st.session_state.isButtonClicked = False
|
238
|
+
|
239
|
+
def toggle_btns():
|
240
|
+
st.session_state.isMagnetButton = not st.session_state.isMagnetButton
|
241
|
+
st.session_state.isButtonClicked = not st.session_state.isButtonClicked
|
242
|
+
|
243
|
+
with st.form(key="magnet_form"):
|
244
|
+
if st.session_state.method == "pygeomag":
|
245
|
+
# st.session_state.isMagnet = False
|
246
|
+
lat = st.number_input("Latitude", -90.0, 90.0, 0.0, step=1.0)
|
247
|
+
lon = st.number_input("Longitude", 0.0, 360.0, 0.1, step=1.0, format="%.4f")
|
248
|
+
depth = st.number_input("Depth", 0, 1000, 0, step=1)
|
249
|
+
year = st.number_input("Year", 2010, 2030, 2025, 1)
|
250
|
+
|
251
|
+
elif st.session_state.method == "API":
|
252
|
+
# st.session_state.isMagnet = False
|
253
|
+
lat = st.number_input("Latitude", -90.0, 90.0, 0.0, step=1.0)
|
254
|
+
lon = st.number_input("Longitude", 0.0, 360.0, 0.1, step=1.0, format="%.4f")
|
255
|
+
year = st.number_input("Year", 1950, 2030, 2025, 1)
|
256
|
+
else:
|
257
|
+
# st.session_state.isMagnet = False
|
258
|
+
mag = [[st.number_input("Declination", -180.0, 180.0, 0.0, 0.1)]]
|
259
|
+
st.session_state.magnet_user_input_VT = mag
|
260
|
+
|
261
|
+
if st.session_state.method == "Manual":
|
262
|
+
button_name = "Accept"
|
263
|
+
else:
|
264
|
+
button_name = "Compute"
|
265
|
+
|
266
|
+
if st.form_submit_button(
|
267
|
+
button_name, on_click=toggle_btns, disabled=st.session_state.isMagnetButton
|
268
|
+
):
|
269
|
+
if st.session_state.method == "pygeomag":
|
270
|
+
mag = magdec(lat, lon, depth, year)
|
271
|
+
st.session_state.velocity_magnet = velocity_modifier(velocity, mag)
|
272
|
+
st.session_state.magnet_lat_VT = lat
|
273
|
+
st.session_state.magnet_lon_VT = lon
|
274
|
+
st.session_state.magnet_year_VT = year
|
275
|
+
st.session_state.magnet_depth_VT = depth
|
276
|
+
st.session_state.angle = np.round(mag[0][0], decimals=3)
|
277
|
+
st.session_state.isMagnetCheck_VT = True
|
278
|
+
st.session_state.isButtonClicked = True
|
279
|
+
|
280
|
+
if st.session_state.method == "API":
|
281
|
+
try:
|
282
|
+
mag = wmm2020api(lat, lon, year)
|
283
|
+
st.session_state.velocity_magnet = velocity_modifier(velocity, mag)
|
284
|
+
st.session_state.magnet_lat_VT = lat
|
285
|
+
st.session_state.magnet_lon_VT = lon
|
286
|
+
st.session_state.magnet_year_VT = year
|
287
|
+
# st.session_state.angle = np.trunc(mag[0][0])
|
288
|
+
st.session_state.angle = np.round(mag[0][0], decimals=3)
|
289
|
+
st.session_state.isMagnetCheck_VT = True
|
290
|
+
st.session_state.isButtonClicked = True
|
291
|
+
except:
|
292
|
+
st.write(
|
293
|
+
":red[Connection error! please check the internet or use manual method]"
|
294
|
+
)
|
295
|
+
else:
|
296
|
+
st.session_state.velocity_magnet = velocity_modifier(velocity, mag)
|
297
|
+
st.session_state.angle = np.round(mag[0][0], decimals=3)
|
298
|
+
st.session_state.isMagnetCheck_VT = True
|
299
|
+
st.session_state.isButtonClicked = True
|
300
|
+
|
301
|
+
if st.session_state.isMagnetCheck_VT:
|
302
|
+
st.write(f"Magnetic declination: {st.session_state.angle}\u00b0")
|
303
|
+
st.write(":green[Magnetic declination correction applied to velocities]")
|
304
|
+
|
305
|
+
magnet_button_reset = st.button(
|
306
|
+
"Reset Magnetic Declination",
|
307
|
+
on_click=toggle_btns,
|
308
|
+
disabled=not st.session_state.isMagnetButton,
|
309
|
+
)
|
310
|
+
if magnet_button_reset:
|
311
|
+
st.session_state.velocity_magnet = np.copy(velocity)
|
312
|
+
st.session_state.isMagnetCheck_VT = False
|
313
|
+
st.session_state.isButtonClicked = False
|
314
|
+
|
315
|
+
with tab2:
|
316
|
+
############# Velocity Cutoffs #################
|
317
|
+
st.header("Velocity Cutoffs", divider="blue")
|
318
|
+
st.write(
|
319
|
+
"""
|
320
|
+
Drop velocities whose magnitude is larger than the threshold.
|
321
|
+
"""
|
322
|
+
)
|
323
|
+
with st.form(key="cutbin_form"):
|
324
|
+
maxuvel = st.number_input(
|
325
|
+
"Maximum Zonal Velocity Cutoff (cm/s)", 0, 2000, 250, 1
|
326
|
+
)
|
327
|
+
maxvvel = st.number_input(
|
328
|
+
"Maximum Meridional Velocity Cutoff (cm/s)", 0, 2000, 250, 1
|
329
|
+
)
|
330
|
+
maxwvel = st.number_input(
|
331
|
+
"Maximum Vertical Velocity Cutoff (cm/s)", 0, 2000, 15, 1
|
332
|
+
)
|
333
|
+
submit_cutoff = st.form_submit_button(label="Submit")
|
334
|
+
|
335
|
+
if submit_cutoff:
|
336
|
+
velocity = st.session_state.velocity_magnet
|
337
|
+
st.session_state.maxuvel_VT = maxuvel
|
338
|
+
st.session_state.maxvvel_VT = maxvvel
|
339
|
+
st.session_state.maxwvel_VT = maxwvel
|
340
|
+
|
341
|
+
st.session_state.velocity_mask_cutoff = velocity_cutoff(
|
342
|
+
velocity[0, :, :], st.session_state.velocity_mask_temp, cutoff=maxuvel
|
343
|
+
)
|
344
|
+
st.session_state.velocity_mask_cutoff = velocity_cutoff(
|
345
|
+
velocity[1, :, :], st.session_state.velocity_mask_temp, cutoff=maxvvel
|
346
|
+
)
|
347
|
+
st.session_state.velocity_mask_cutoff = velocity_cutoff(
|
348
|
+
velocity[2, :, :], st.session_state.velocity_mask_temp, cutoff=maxwvel
|
349
|
+
)
|
350
|
+
st.session_state.velocity_mask_temp = np.copy(
|
351
|
+
st.session_state.velocity_mask_cutoff
|
352
|
+
)
|
353
|
+
st.session_state.isCutoffCheck_VT = True
|
354
|
+
|
355
|
+
if st.session_state.isCutoffCheck_VT:
|
356
|
+
st.success("Cutoff Applied")
|
357
|
+
a = {
|
358
|
+
"Max. Zonal Velocity": maxuvel,
|
359
|
+
"Max. Meridional Velocity": maxvvel,
|
360
|
+
"Max. Vertical Velocity": maxwvel,
|
361
|
+
}
|
362
|
+
st.write(a)
|
363
|
+
|
364
|
+
def reset_button_cutoff():
|
365
|
+
st.session_state.isCutoffCheck_VT = False
|
366
|
+
st.session_state.velocity_mask_temp = np.copy(
|
367
|
+
st.session_state.velocity_mask_default
|
368
|
+
)
|
369
|
+
st.session_state.velocity_mask_cutoff = np.copy(
|
370
|
+
st.session_state.velocity_mask_default
|
371
|
+
)
|
372
|
+
|
373
|
+
reset_cutoff = st.button("Reset Cutoff to default", on_click=reset_button_cutoff)
|
374
|
+
if reset_cutoff:
|
375
|
+
st.info("Cutoff Test is reset")
|
376
|
+
|
377
|
+
|
378
|
+
with tab3:
|
379
|
+
############## DESPIKE DATA #################
|
380
|
+
st.header("Despike Data", divider="blue")
|
381
|
+
st.write("""A rolling median filter is applied to remove spikes from the data.
|
382
|
+
The kernel size determines the number of ensembles (time interval) for the filter window.
|
383
|
+
The standard deviation specifies the maximum allowable deviation to remove the spike.""")
|
384
|
+
|
385
|
+
# time_interval = pd.Timedelta(st.session_state.date[-1] - st.session_state.date[0]).seconds/(3600*st.session_state.head.ensembles)
|
386
|
+
|
387
|
+
st.write("Time interval: ", st.session_state.date[1] - st.session_state.date[0])
|
388
|
+
|
389
|
+
despike_kernel = st.number_input(
|
390
|
+
"Enter Despike kernel Size for Median Filter",
|
391
|
+
0,
|
392
|
+
st.session_state.head.ensembles,
|
393
|
+
5,
|
394
|
+
1,
|
395
|
+
)
|
396
|
+
|
397
|
+
despike_cutoff = st.number_input(
|
398
|
+
"Standard Deviation Cutoff for Spike Removal", 0.1, 10.0, 3.0, 0.1
|
399
|
+
)
|
400
|
+
despike_button = st.button("Despike")
|
401
|
+
if despike_button:
|
402
|
+
st.session_state.despike_kernel_VT = despike_kernel
|
403
|
+
st.session_state.despike_cutoff_VT = despike_cutoff
|
404
|
+
|
405
|
+
st.session_state.velocity_mask_despike = despike(
|
406
|
+
velocity[0, :, :],
|
407
|
+
st.session_state.velocity_mask_temp,
|
408
|
+
kernel_size=despike_kernel,
|
409
|
+
cutoff=despike_cutoff,
|
410
|
+
)
|
411
|
+
st.session_state.velocity_mask_despike = despike(
|
412
|
+
velocity[1, :, :],
|
413
|
+
st.session_state.velocity_mask_temp,
|
414
|
+
kernel_size=despike_kernel,
|
415
|
+
cutoff=despike_cutoff,
|
416
|
+
)
|
417
|
+
|
418
|
+
# Reset the temporary mask
|
419
|
+
st.session_state.velocity_mask_temp = np.copy(
|
420
|
+
st.session_state.velocity_mask_despike
|
421
|
+
)
|
422
|
+
st.session_state.isDespikeCheck_VT = True
|
423
|
+
|
424
|
+
if st.session_state.isDespikeCheck_VT:
|
425
|
+
st.success("Data Despiked")
|
426
|
+
b = {
|
427
|
+
"kernel Size": despike_kernel,
|
428
|
+
"Despike Cutoff": despike_cutoff,
|
429
|
+
}
|
430
|
+
st.write(b)
|
431
|
+
|
432
|
+
def reset_button_despike():
|
433
|
+
st.session_state.isDespikeCheck_VT = False
|
434
|
+
if st.session_state.isCutoffCheck_VT:
|
435
|
+
st.session_state.velocity_mask_temp = np.copy(
|
436
|
+
st.session_state.velocity_mask_cutoff
|
437
|
+
)
|
438
|
+
st.session_state.velocity_mask_despike = np.copy(
|
439
|
+
st.session_state.velocity_mask_cutoff
|
440
|
+
)
|
441
|
+
else:
|
442
|
+
st.session_state.velocity_mask_temp = np.copy(
|
443
|
+
st.session_state.velocity_mask_default
|
444
|
+
)
|
445
|
+
st.session_state.velocity_mask_despike = np.copy(
|
446
|
+
st.session_state.velocity_mask_default
|
447
|
+
)
|
448
|
+
|
449
|
+
reset_despike = st.button("Reset Despike to default", on_click=reset_button_despike)
|
450
|
+
if reset_despike:
|
451
|
+
st.info("Despike Test is reset")
|
452
|
+
|
453
|
+
with tab4:
|
454
|
+
st.header("Remove Flatline", divider="blue")
|
455
|
+
|
456
|
+
st.write("""
|
457
|
+
Flatline removal detects segments of data where values remain constant over
|
458
|
+
a specified interval. The kernel size defines the number of consecutive
|
459
|
+
ensembles (time intervals) considered in the check, while the threshold sets
|
460
|
+
the maximum allowable variation.
|
461
|
+
""")
|
462
|
+
|
463
|
+
st.write("Time interval: ", st.session_state.date[1] - st.session_state.date[0])
|
464
|
+
|
465
|
+
flatline_kernel = st.number_input("Enter Flatline kernel Size", 0, 100, 13, 1)
|
466
|
+
flatline_cutoff = st.number_input("Enter Flatline deviation (mm/s)", 0, 100, 1, 1)
|
467
|
+
|
468
|
+
flatline_button = st.button("Remove Flatline")
|
469
|
+
|
470
|
+
if flatline_button:
|
471
|
+
st.session_state.flatline_kernel_VT = flatline_kernel
|
472
|
+
st.session_state.flatline_cutoff_VT = flatline_cutoff
|
473
|
+
|
474
|
+
st.session_state.velocity_mask_flatline = flatline(
|
475
|
+
velocity[0, :, :],
|
476
|
+
st.session_state.velocity_mask_temp,
|
477
|
+
kernel_size=flatline_kernel,
|
478
|
+
cutoff=flatline_cutoff,
|
479
|
+
)
|
480
|
+
st.session_state.velocity_mask_flatline = flatline(
|
481
|
+
velocity[1, :, :],
|
482
|
+
st.session_state.velocity_mask_temp,
|
483
|
+
kernel_size=flatline_kernel,
|
484
|
+
cutoff=flatline_cutoff,
|
485
|
+
)
|
486
|
+
st.session_state.velocity_mask_flatline = flatline(
|
487
|
+
velocity[2, :, :],
|
488
|
+
st.session_state.velocity_mask_temp,
|
489
|
+
kernel_size=flatline_kernel,
|
490
|
+
cutoff=flatline_cutoff,
|
491
|
+
)
|
492
|
+
# Modify the temporary mask file
|
493
|
+
st.session_state.velocity_mask_temp = np.copy(
|
494
|
+
st.session_state.velocity_mask_flatline
|
495
|
+
)
|
496
|
+
st.session_state.isFlatlineCheck = True
|
497
|
+
|
498
|
+
if st.session_state.isFlatlineCheck:
|
499
|
+
st.success("Flatline Removed")
|
500
|
+
b = {
|
501
|
+
"kernel Size": flatline_kernel,
|
502
|
+
"Flatline Cutoff": flatline_cutoff,
|
503
|
+
}
|
504
|
+
st.write(b)
|
505
|
+
|
506
|
+
def reset_button_flatline():
|
507
|
+
st.session_state.isFlatlineCheck = False
|
508
|
+
if st.session_state.isDespikeCheck_VT:
|
509
|
+
st.session_state.velocity_mask_temp = np.copy(
|
510
|
+
st.session_state.velocity_mask_despike
|
511
|
+
)
|
512
|
+
st.session_state.velocity_mask_flatline = np.copy(
|
513
|
+
st.session_state.velocity_mask_despike
|
514
|
+
)
|
515
|
+
elif st.session_state.isCutoffCheck_VT:
|
516
|
+
st.session_state.velocity_mask_temp = np.copy(
|
517
|
+
st.session_state.velocity_mask_cutoff
|
518
|
+
)
|
519
|
+
st.session_state.velocity_mask_flatline = np.copy(
|
520
|
+
st.session_state.velocity_mask_cutoff
|
521
|
+
)
|
522
|
+
else:
|
523
|
+
st.session_state.velocity_mask_temp = np.copy(
|
524
|
+
st.session_state.velocity_mask_default
|
525
|
+
)
|
526
|
+
st.session_state.velocity_mask_flatline = np.copy(
|
527
|
+
st.session_state.velocity_mask_default
|
528
|
+
)
|
529
|
+
|
530
|
+
reset_despike = st.button(
|
531
|
+
"Reset Flatline to default", on_click=reset_button_flatline
|
532
|
+
)
|
533
|
+
if reset_despike:
|
534
|
+
st.info("Flatline Test is reset")
|
535
|
+
|
536
|
+
|
537
|
+
##################### SAVE DATA ###################
|
538
|
+
with tab5:
|
539
|
+
st.header("Save & Reset Data", divider="blue")
|
540
|
+
|
541
|
+
def save_velocitytest():
|
542
|
+
st.session_state.isVelocityTest = True
|
543
|
+
st.session_state.isFirstVelocityVisit = False
|
544
|
+
st.session_state.velocity_mask = st.session_state.velocity_mask_temp
|
545
|
+
|
546
|
+
st.session_state.isSensorPageReturn = True
|
547
|
+
st.session_state.isQCPageReturn = True
|
548
|
+
st.session_state.isProfilePageReturn = True
|
549
|
+
|
550
|
+
col1, col2 = st.columns([1, 1])
|
551
|
+
with col1:
|
552
|
+
save_button = st.button(label="Save Data", on_click=save_velocitytest)
|
553
|
+
if save_button:
|
554
|
+
st.write(":green[Mask data saved]")
|
555
|
+
# Status Summary Table
|
556
|
+
status_summary = pd.DataFrame(
|
557
|
+
[
|
558
|
+
[
|
559
|
+
"Magnetic Declination",
|
560
|
+
"True" if st.session_state.isButtonClicked else "False",
|
561
|
+
],
|
562
|
+
[
|
563
|
+
"Velocity Cutoffs",
|
564
|
+
"True" if st.session_state.isCutoffCheck_VT else "False",
|
565
|
+
],
|
566
|
+
[
|
567
|
+
"Despike Data",
|
568
|
+
"True" if st.session_state.isDespikeCheck_VT else "False",
|
569
|
+
],
|
570
|
+
[
|
571
|
+
"Remove Flatline",
|
572
|
+
"True" if st.session_state.isFlatlineCheck else "False",
|
573
|
+
],
|
574
|
+
],
|
575
|
+
columns=["Test", "Status"],
|
576
|
+
)
|
577
|
+
|
578
|
+
# Define a mapping function for styling
|
579
|
+
def status_color_map(value):
|
580
|
+
if value == "True":
|
581
|
+
return "background-color: green; color: white"
|
582
|
+
elif value == "False":
|
583
|
+
return "background-color: red; color: white"
|
584
|
+
else:
|
585
|
+
return ""
|
586
|
+
|
587
|
+
# Apply styles using Styler.apply
|
588
|
+
styled_table = status_summary.style.set_properties(
|
589
|
+
**{"text-align": "center"}
|
590
|
+
)
|
591
|
+
styled_table = styled_table.map(status_color_map, subset=["Status"])
|
592
|
+
|
593
|
+
# Display the styled table
|
594
|
+
st.write(styled_table.to_html(), unsafe_allow_html=True)
|
595
|
+
else:
|
596
|
+
st.write(":red[Data not saved]")
|
597
|
+
|
598
|
+
with col2:
|
599
|
+
st.button(label="Reset Data", on_click=reset_velocitytest)
|
600
|
+
st.info("Velocity test reset to default")
|