pyadps 0.1.0__py3-none-any.whl → 0.1.0b0__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.
@@ -0,0 +1,389 @@
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 utils.profile_test import side_lobe_beam_angle
9
+ from utils.regrid import regrid2d, regrid3d
10
+ from utils.signal_quality import default_mask
11
+
12
+ if "flead" not in st.session_state:
13
+ st.write(":red[Please Select Data!]")
14
+ st.stop()
15
+
16
+ # `maskp` holds the temporary changes in the page
17
+ # `profile_mask`
18
+ if "maskp" not in st.session_state:
19
+ if "qc_mask" not in st.session_state:
20
+ st.session_state.maskp = np.copy(st.session_state.orig_mask)
21
+ else:
22
+ st.session_state.maskp = np.copy(st.session_state.qc_mask)
23
+
24
+
25
+ if st.session_state.isQCMask:
26
+ st.write(":grey[Working on a saved mask file ...]")
27
+ if st.session_state.isProfileMask:
28
+ st.write(
29
+ ":orange[Warning: Profile test already completed. Reset to change settings.]"
30
+ )
31
+ reset_selectbox = st.selectbox(
32
+ "Choose reset option",
33
+ ("QC Test", "Default"),
34
+ index=None,
35
+ placeholder="Reset mask to ...",
36
+ )
37
+ if reset_selectbox == "Default":
38
+ st.write("Default mask file selected")
39
+ st.session_state.maskp = st.session_state.orig_mask
40
+ elif reset_selectbox == "QC Test":
41
+ st.write("QC Test mask file selected")
42
+ st.session_state.maskp = st.session_state.qc_mask
43
+ else:
44
+ st.session_state.maskp = st.session_state.profile_mask
45
+ else:
46
+ st.session_state.maskp = st.session_state.qc_mask
47
+ else:
48
+ st.write(":orange[Creating a new mask file ...]")
49
+
50
+ mask = st.session_state.maskp
51
+
52
+ # Load data
53
+ flobj = st.session_state.flead
54
+ vlobj = st.session_state.vlead
55
+ velocity = st.session_state.velocity
56
+ echo = st.session_state.echo
57
+ correlation = st.session_state.correlation
58
+ pgood = st.session_state.pgood
59
+ fdata = flobj.fleader
60
+ vdata = vlobj.vleader
61
+
62
+
63
+ ensembles = st.session_state.head.ensembles
64
+ cells = flobj.field()["Cells"]
65
+ x = np.arange(0, ensembles, 1)
66
+ y = np.arange(0, cells, 1)
67
+
68
+ # Regrided data
69
+ if "velocity_regrid" not in st.session_state:
70
+ st.session_state.echo_regrid = np.copy(echo)
71
+ st.session_state.velocity_regrid = np.copy(velocity)
72
+ st.session_state.correlation_regrid = np.copy(correlation)
73
+ st.session_state.pgood_regrid = np.copy(pgood)
74
+ st.session_state.mask_regrid = np.copy(mask)
75
+
76
+
77
+ # @st.cache_data
78
+ def fillplot_plotly(
79
+ data, title="data", maskdata=None, missing=-32768, colorscale="balance"
80
+ ):
81
+ fig = FigureResampler(go.Figure())
82
+ data1 = np.where(data == missing, np.nan, data)
83
+ fig.add_trace(
84
+ go.Heatmap(
85
+ z=data1,
86
+ x=x,
87
+ y=y,
88
+ colorscale=colorscale,
89
+ hoverongaps=False,
90
+ )
91
+ )
92
+ if mask is not None:
93
+ fig.add_trace(
94
+ go.Heatmap(
95
+ z=maskdata,
96
+ x=x,
97
+ y=y,
98
+ colorscale="gray",
99
+ hoverongaps=False,
100
+ showscale=False,
101
+ opacity=0.5,
102
+ )
103
+ )
104
+ fig.update_layout(
105
+ xaxis=dict(showline=True, mirror=True),
106
+ yaxis=dict(showline=True, mirror=True),
107
+ title_text=title,
108
+ )
109
+ fig.update_xaxes(title="Ensembles")
110
+ fig.update_yaxes(title="Depth Cells")
111
+ st.plotly_chart(fig)
112
+
113
+
114
+ def fillselect_plotly(data, title="data", colorscale="balance"):
115
+ fig = FigureResampler(go.Figure())
116
+ data1 = np.where(data == -32768, None, data)
117
+ fig.add_trace(
118
+ go.Heatmap(
119
+ z=data1,
120
+ x=x,
121
+ y=y,
122
+ colorscale=colorscale,
123
+ hoverongaps=False,
124
+ )
125
+ )
126
+ # fig.add_trace(
127
+ # go.Scatter(x=X, y=Y, marker=dict(color="black", size=16), mode="lines+markers")
128
+ # )
129
+ fig.update_layout(
130
+ xaxis=dict(showline=True, mirror=True),
131
+ yaxis=dict(showline=True, mirror=True),
132
+ title_text=title,
133
+ )
134
+ fig.update_xaxes(title="Ensembles")
135
+ fig.update_yaxes(title="Depth Cells")
136
+ fig.update_layout(clickmode="event+select")
137
+ event = st.plotly_chart(fig, key="1", on_select="rerun", selection_mode="box")
138
+
139
+ return event
140
+
141
+
142
+ @st.cache_data
143
+ def trim_ends(start_ens=0, end_ens=0, ens_range=20):
144
+ depth = vdata["Depth of Transducer"] / 10
145
+ fig = make_subplots(
146
+ rows=1,
147
+ cols=2,
148
+ subplot_titles=[
149
+ "Deployment Ensemble",
150
+ "Recovery Ensemble",
151
+ ],
152
+ )
153
+ fig.add_trace(
154
+ go.Scatter(
155
+ x=x[0:ens_range],
156
+ y=depth[0:ens_range],
157
+ name="Deployment",
158
+ mode="markers",
159
+ marker=dict(color="#1f77b4"),
160
+ ),
161
+ row=1,
162
+ col=1,
163
+ )
164
+
165
+ fig.add_trace(
166
+ go.Scatter(
167
+ x=x[-1 * ens_range :],
168
+ y=depth[-1 * ens_range :],
169
+ name="Recovery",
170
+ mode="markers",
171
+ marker=dict(color="#17becf"),
172
+ ),
173
+ row=1,
174
+ col=2,
175
+ )
176
+
177
+ if start_ens > x[0]:
178
+ fig.add_trace(
179
+ go.Scatter(
180
+ x=x[0:start_ens],
181
+ y=depth[0:start_ens],
182
+ name="Selected Points (D)",
183
+ mode="markers",
184
+ marker=dict(color="red"),
185
+ ),
186
+ row=1,
187
+ col=1,
188
+ )
189
+
190
+ if end_ens < x[-1] + 1:
191
+ fig.add_trace(
192
+ go.Scatter(
193
+ x=x[end_ens : x[-1] + 1],
194
+ y=depth[end_ens : x[-1] + 1],
195
+ name="Selected Points (R)",
196
+ mode="markers",
197
+ marker=dict(color="orange"),
198
+ ),
199
+ row=1,
200
+ col=2,
201
+ )
202
+
203
+ fig.update_layout(height=600, width=800, title_text="Transducer depth")
204
+ fig.update_xaxes(title="Ensembles")
205
+ fig.update_yaxes(title="Depth (m)")
206
+ st.plotly_chart(fig)
207
+
208
+
209
+ st.header("Profile Test")
210
+
211
+ ############## TRIM ENDS #################
212
+ st.header("Trim Ends", divider="blue")
213
+ n = 20
214
+ m = 20
215
+ if "update_mask" not in st.session_state:
216
+ st.session_state.update_mask = False
217
+ st.session_state.endpoints = None
218
+ if "update_mask_cutbin" not in st.session_state:
219
+ st.session_state.update_mask_cutbin = False
220
+
221
+ ens_range = st.number_input("Change range", x[0], x[-1], 20)
222
+ start_ens = st.slider("Deployment Ensembles", 0, ens_range, 0)
223
+ end_ens = st.slider("Recovery Ensembles", x[-1] - ens_range, x[-1] + 1, x[-1] + 1)
224
+
225
+ n = int(ens_range)
226
+
227
+ if start_ens or end_ens:
228
+ trim_ends(start_ens=start_ens, end_ens=end_ens, ens_range=n)
229
+ st.session_state.update_mask = False
230
+
231
+ update_mask = st.button("Update mask data")
232
+ if update_mask:
233
+ if start_ens > 0:
234
+ mask[:, :start_ens] = 1
235
+
236
+ if end_ens < x[-1]:
237
+ mask[:, end_ens:] = 1
238
+
239
+ st.session_state.ens_range = ens_range
240
+ st.session_state.start_ens = start_ens
241
+ st.session_state.end_ens = end_ens
242
+ st.session_state.maskp = mask
243
+ st.write(":green[mask data updated]")
244
+ st.session_state.endpoints = np.array(
245
+ [st.session_state.start_ens, st.session_state.end_ens]
246
+ )
247
+ st.write(st.session_state.endpoints)
248
+ st.session_state.update_mask = True
249
+
250
+ if not st.session_state.update_mask:
251
+ st.write(":red[mask data not updated]")
252
+
253
+
254
+ ############ CUT BINS (SIDE LOBE) ############################
255
+ st.header("Cut Bins: Side Lobe Contamination", divider="blue")
256
+ st.write(
257
+ """
258
+ The side lobe echos from hard surface such as sea surface or bottom of the ocean can contaminate
259
+ data closer to this region. The data closer to the surface or bottom can be removed using
260
+ the relation between beam angle and the thickness of the contaminated layer.
261
+ """
262
+ )
263
+
264
+ # Reset mask
265
+ mask = st.session_state.maskp
266
+ beam = st.radio("Select beam", (1, 2, 3, 4), horizontal=True)
267
+ beam = beam - 1
268
+ st.session_state.beam = beam
269
+ fillplot_plotly(echo[beam, :, :], title="Echo Intensity")
270
+
271
+ with st.form(key="cutbin_form"):
272
+ extra_cells = st.number_input("Additional Cells to Delete", 0, 10, 0)
273
+ cut_bins_mask = st.form_submit_button(label="Cut bins")
274
+
275
+ if cut_bins_mask:
276
+ st.session_state.extra_cells = extra_cells
277
+ mask = side_lobe_beam_angle(flobj, vlobj, mask, extra_cells=extra_cells)
278
+ fillplot_plotly(
279
+ echo[beam, :, :],
280
+ title="Echo Intensity (Masked)",
281
+ maskdata=mask,
282
+ )
283
+ fillplot_plotly(mask, colorscale="greys", title="Mask Data")
284
+
285
+ update_mask_cutbin = st.button("Update mask file after cutbin")
286
+ if update_mask_cutbin:
287
+ st.session_state.maskp = mask
288
+ st.write(":green[mask file updated]")
289
+ st.session_state.update_mask_cutbin = True
290
+
291
+ if not st.session_state.update_mask_cutbin:
292
+ st.write(":red[mask file not updated]")
293
+
294
+
295
+ ############ CUT BINS: Manual #################
296
+ st.header("Cut Bins: Manual", divider="blue")
297
+
298
+
299
+ ############ REGRID ###########################################
300
+ st.header("Regrid Depth Cells", divider="blue")
301
+
302
+ st.write(
303
+ """
304
+ When the ADCP buoy has vertical oscillations (greater than depth cell size),
305
+ the depth bins has to be regridded based on the pressure sensor data. The data
306
+ can be regrided either till the surface or till the last bin.
307
+ If the `bin` option is selected, ensure that the end data are trimmed.
308
+ """
309
+ )
310
+
311
+ last_cell = st.radio(
312
+ "Select the depth of last bin for regridding", ("Bin", "Surface"), horizontal=True
313
+ )
314
+ st.session_state.last_cell = last_cell
315
+ st.write(last_cell)
316
+ regrid_button = st.button(label="Regrid Data")
317
+
318
+
319
+ if regrid_button:
320
+ st.write(st.session_state.endpoints)
321
+ z, st.session_state.velocity_regrid = regrid3d(
322
+ flobj, vlobj, velocity, -32768, trimends=st.session_state.endpoints
323
+ )
324
+ st.write(":grey[Regrided velocity ...]")
325
+ z, st.session_state.echo_regrid = regrid3d(
326
+ flobj, vlobj, echo, -32768, trimends=st.session_state.endpoints
327
+ )
328
+ st.write(":grey[Regrided echo intensity ...]")
329
+ z, st.session_state.correlation_regrid = regrid3d(
330
+ flobj, vlobj, correlation, -32768, trimends=st.session_state.endpoints
331
+ )
332
+ st.write(":grey[Regrided correlation...]")
333
+ z, st.session_state.pgood_regrid = regrid3d(
334
+ flobj, vlobj, pgood, -32768, trimends=st.session_state.endpoints
335
+ )
336
+ st.write(":grey[Regrided percent good...]")
337
+ z, st.session_state.mask_regrid = regrid2d(
338
+ flobj, vlobj, mask, 1, trimends=st.session_state.endpoints
339
+ )
340
+
341
+ st.session_state.depth = z
342
+
343
+ st.write(":grey[Regrided mask...]")
344
+ st.write(":green[All data regrided!]")
345
+
346
+ st.write("No. of grid depth bins before regridding: ", np.shape(velocity)[1])
347
+ st.write(
348
+ "No. of grid depth bins after regridding: ",
349
+ np.shape(st.session_state.velocity_regrid)[1],
350
+ )
351
+ fillplot_plotly(
352
+ st.session_state.velocity_regrid[0, :, :], title="Regridded Velocity File"
353
+ )
354
+ fillplot_plotly(velocity[0, :, :], title="Original File")
355
+ fillplot_plotly(
356
+ st.session_state.mask_regrid, colorscale="greys", title="Regridded Mask File"
357
+ )
358
+
359
+ st.session_state.isGrid = True
360
+ st.session_state.isGridSave = False
361
+
362
+
363
+ ########### Save and Reset Mask ##############
364
+ st.header("Save & Reset Mask Data", divider="blue")
365
+
366
+ col1, col2 = st.columns([1, 1])
367
+ with col1:
368
+ save_mask_button = st.button(label="Save Mask Data")
369
+ if save_mask_button:
370
+ if st.session_state.isGrid:
371
+ st.session_state.profile_mask = st.session_state.mask_regrid
372
+ st.session_state.isGridSave = True
373
+ else:
374
+ st.session_state.profile_mask = st.session_state.maskp
375
+ st.session_state.isProfileMask = True
376
+ st.session_state.isVelocityMask = False
377
+ st.write(":green[Mask data saved]")
378
+ else:
379
+ st.write(":red[Mask data not saved]")
380
+ with col2:
381
+ reset_mask_button = st.button("Reset mask data")
382
+ if reset_mask_button:
383
+ st.session_state.maskp = np.copy(st.session_state.orig_mask)
384
+ st.write(":green[Mask data is reset to default]")
385
+ st.session_state.isQCMask = False
386
+ st.session_state.isProfileMask = False
387
+ st.session_state.isGrid = False
388
+ st.session_state.isGridSave = False
389
+ st.session_state.isVelocityMask = False
@@ -0,0 +1,293 @@
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 (despike, flatline, magnetic_declination,
12
+ velocity_cutoff)
13
+
14
+ if "flead" not in st.session_state:
15
+ st.write(":red[Please Select Data!]")
16
+ st.stop()
17
+
18
+ flobj = st.session_state.flead
19
+ vlobj = st.session_state.vlead
20
+ fdata = flobj.fleader
21
+ vdata = vlobj.vleader
22
+
23
+
24
+ ####### Initialize Mask File ##############
25
+ # Is this the best way?
26
+ if st.session_state.isProfileMask or st.session_state.isQCMask:
27
+ st.write(":grey[Working on a saved mask file ...]")
28
+ if st.session_state.isVelocityMask:
29
+ st.write(
30
+ ":orange[Warning: Velocity test already completed. Reset to change settings.]"
31
+ )
32
+ reset_selectbox = st.selectbox(
33
+ "Choose reset option",
34
+ ("Profile Test", "QC Test", "Default"),
35
+ index=None,
36
+ placeholder="Reset mask to ...",
37
+ )
38
+ if reset_selectbox == "Default":
39
+ st.write("Default mask file selected")
40
+ st.session_state.maskd = st.session_state.orig_mask
41
+ st.session_state.dummyvelocity = st.session_state.velocity
42
+ elif reset_selectbox == "QC Test":
43
+ st.write("QC Test mask file selected")
44
+ st.session_state.maskd = st.session_state.qc_mask
45
+ st.session_state.dummyvelocity = st.session_state.velocity
46
+ elif reset_selectbox == "Profile Test":
47
+ st.session_state.maskd = st.session_state.profile_mask
48
+ if st.session_state.isGridSave:
49
+ st.session_state.dummyvelocity = st.session_state.velocity_regrid
50
+ else:
51
+ st.session_state.dummyvelocity = st.session_state.velocity
52
+ else:
53
+ st.session_state.maskd = st.session_state.velocity_mask
54
+ st.session_state.dummyvelocity = st.session_state.velocity
55
+ else:
56
+ if st.session_state.isProfileMask:
57
+ st.session_state.maskd = st.session_state.profile_mask
58
+ elif st.session_state.isQCMask:
59
+ st.session_state.maskd = st.session_state.qc_mask
60
+ else:
61
+ st.session_state.maskd = st.session_state.orig_mask
62
+ else:
63
+ st.write(":grey[Creating a new mask file ...]")
64
+
65
+
66
+ if "isCutoff" not in st.session_state:
67
+ st.session_state.isMagnet = False
68
+ st.session_state.isCutoff = False
69
+ st.session_state.isDespike = False
70
+ st.session_state.isFlatline = False
71
+
72
+ if "maskd" not in st.session_state:
73
+ if st.session_state.isProfileMask:
74
+ st.session_state.maskd = np.copy(st.session_state.profile_mask)
75
+ elif st.session_state.isQCMask:
76
+ st.session_state.maskd = np.copy(st.session_state.qc_mask)
77
+ else:
78
+ st.session_state.maskd = np.copy(st.session_state.orig_mask)
79
+
80
+ # If data are not regrided use the default one
81
+ if st.session_state.isGridSave:
82
+ st.session_state.dummyvelocity = np.copy(st.session_state.velocity_regrid)
83
+ else:
84
+ st.session_state.dummyvelocity = np.copy(st.session_state.velocity)
85
+
86
+ velocity = st.session_state.dummyvelocity
87
+
88
+ ensembles = st.session_state.head.ensembles
89
+ cells = flobj.field()["Cells"]
90
+ x = np.arange(0, ensembles, 1)
91
+ y = np.arange(0, cells, 1)
92
+
93
+
94
+ ########### Introduction ##########
95
+ st.header("Velocity Test", divider="orange")
96
+
97
+ st.write(
98
+ """
99
+ The processing in this page apply only to the velocity data.
100
+ """
101
+ )
102
+
103
+ ############ Magnetic Declination ##############
104
+ st.header("Magnetic Declination", divider="blue")
105
+ st.write(
106
+ """
107
+ The magnetic declination is obtained from World Magnetic Model 2020 (WMM2020).
108
+ The python wrapper module `wmm2020` is available from this [Link](https://github.com/space-physics/wmm2020).
109
+ If the magnetic declination is reset, re-run the remaining tests again.
110
+ """
111
+ )
112
+
113
+ if "isMagnetButton" not in st.session_state:
114
+ st.session_state.isMagnetButton = False
115
+
116
+
117
+ def toggle_btns():
118
+ st.session_state.isMagnetButton = not st.session_state.isMagnetButton
119
+
120
+
121
+ with st.form(key="magnet_form"):
122
+ lat = st.number_input("Latitude", -90.0, 90.0, 0.0, step=1.0)
123
+ lon = st.number_input("Longitude", 0.0, 360.0, 0.1, step=1.0, format="%.4f")
124
+ depth = st.number_input("Depth", 0, 1000, 0, step=1)
125
+ year = st.number_input("Year", 1950, 2100, 2024, 1)
126
+
127
+ if st.form_submit_button(
128
+ "Compute", on_click=toggle_btns, disabled=st.session_state.isMagnetButton
129
+ ):
130
+ st.session_state.dummyvelocity, mag = magnetic_declination(
131
+ velocity, lat, lon, depth, year
132
+ )
133
+ st.session_state.lat = lat
134
+ st.session_state.lon = lon
135
+ st.session_state.magnetic_dec_depth = depth
136
+ st.session_state.year = year
137
+ st.session_state.angle = np.trunc(mag[0][0])
138
+ st.session_state.isMagnet = True
139
+
140
+ if st.session_state.isMagnet:
141
+ st.write(f"Magnetic declination: {st.session_state.angle}\u00b0")
142
+ st.write(":green[Magnetic declination correction applied to velocities]")
143
+
144
+ if st.button(
145
+ "Reset Magnetic Declination",
146
+ on_click=toggle_btns,
147
+ disabled=not st.session_state.isMagnetButton,
148
+ ):
149
+ st.session_state.dummyvelocity = np.copy(velocity)
150
+ st.session_state.isMagnet = False
151
+
152
+ ############# Velocity Cutoffs #################
153
+ st.header("Velocity Cutoffs", divider="blue")
154
+ st.write(
155
+ """
156
+ Drop velocities whose magnitude is larger than the threshold.
157
+ """
158
+ )
159
+ with st.form(key="cutbin_form"):
160
+ maxuvel = st.number_input("Maximum Zonal Velocity Cutoff (cm/s)", 0, 2000, 250, 1)
161
+ maxvvel = st.number_input(
162
+ "Maximum Meridional Velocity Cutoff (cm/s)", 0, 2000, 250, 1
163
+ )
164
+ maxwvel = st.number_input("Maximum Vertical Velocity Cutoff (cm/s)", 0, 2000, 15, 1)
165
+ submit_cutoff = st.form_submit_button(label="Submit")
166
+
167
+ if submit_cutoff:
168
+
169
+ st.session_state.maxuvel = maxuvel
170
+ st.session_state.maxvvel = maxvvel
171
+ st.session_state.maxwvel = maxwvel
172
+
173
+
174
+ st.session_state.maskd = velocity_cutoff(
175
+ velocity[0, :, :], st.session_state.maskd, cutoff=maxuvel
176
+ )
177
+ st.session_state.maskd = velocity_cutoff(
178
+ velocity[1, :, :], st.session_state.maskd, cutoff=maxvvel
179
+ )
180
+ st.session_state.maskd = velocity_cutoff(
181
+ velocity[2, :, :], st.session_state.maskd, cutoff=maxwvel
182
+ )
183
+ st.session_state.isCutoff = True
184
+
185
+
186
+ if st.session_state.isCutoff:
187
+ st.write("Cutoff Applied")
188
+ a = {
189
+ "Max. Zonal Velocity": maxuvel,
190
+ "Max. Meridional Velocity": maxvvel,
191
+ "Max. Vertical Velocity": maxwvel,
192
+ }
193
+ st.write(a)
194
+
195
+
196
+ ############## DESPIKE DATA #################
197
+ st.header("Despike Data", divider="blue")
198
+ despike_kernal = st.number_input(
199
+ "Enter Despike Kernal Size for Median Filter", 0, 1000, 5, 1
200
+ )
201
+ despike_cutoff = st.number_input("Enter Despike Cutoff (mm/s)", 0, 1000, 150, 1)
202
+ despike_button = st.button("Despike")
203
+ if despike_button:
204
+
205
+ st.session_state.despike_kernal = despike_kernal
206
+ st.session_state.despike_cutoff = despike_cutoff
207
+
208
+ st.session_state.maskd = despike(
209
+ velocity[0, :, :],
210
+ st.session_state.maskd,
211
+ kernal_size=despike_kernal,
212
+ cutoff=despike_cutoff,
213
+ )
214
+ st.session_state.maskd = despike(
215
+ velocity[1, :, :],
216
+ st.session_state.maskd,
217
+ kernal_size=despike_kernal,
218
+ cutoff=despike_cutoff,
219
+ )
220
+ st.session_state.isDespike = True
221
+
222
+ if st.session_state.isDespike:
223
+ st.write("Data Despiked")
224
+ b = {
225
+ "Kernal Size": despike_kernal,
226
+ "Despike Cutoff": despike_cutoff,
227
+ }
228
+ st.write(b)
229
+
230
+ st.header("Remove Flatline", divider="blue")
231
+ flatline_kernal = st.number_input("Enter Flatline Kernal Size", 0, 100, 13, 1)
232
+ flatline_cutoff = st.number_input("Enter Flatline deviation", 0, 100, 1, 1)
233
+
234
+ flatline_button = st.button("Remove Flatline")
235
+
236
+ if flatline_button:
237
+ st.session_state.flatline_kernal = flatline_kernal
238
+ st.session_state.flatline_cutoff = flatline_cutoff
239
+
240
+ st.session_state.maskd = flatline(
241
+ velocity[0, :, :],
242
+ st.session_state.maskd,
243
+ kernal_size=flatline_kernal,
244
+ cutoff=flatline_cutoff,
245
+ )
246
+ st.session_state.maskd = flatline(
247
+ velocity[1, :, :],
248
+ st.session_state.maskd,
249
+ kernal_size=flatline_kernal,
250
+ cutoff=flatline_cutoff,
251
+ )
252
+ st.session_state.maskd = flatline(
253
+ velocity[2, :, :],
254
+ st.session_state.maskd,
255
+ kernal_size=flatline_kernal,
256
+ cutoff=flatline_cutoff,
257
+ )
258
+ st.session_state.isFlatline = True
259
+
260
+ if st.session_state.isFlatline:
261
+ st.write(":green[Flatline Removed]")
262
+ b = {
263
+ "Kernal Size": flatline_kernal,
264
+ "Flatline Cutoff": flatline_cutoff,
265
+ }
266
+ st.write(b)
267
+
268
+
269
+ ##################### SAVE DATA ###################
270
+ st.header("Save & Reset Data", divider="blue")
271
+
272
+
273
+ def reset_data():
274
+ st.session_state.dummyvelocity = np.copy(st.session_state.velocity_regrid)
275
+ st.session_state.isMagnet = False
276
+ st.session_state.isCutoff = False
277
+ st.session_state.isDespike = False
278
+ st.session_state.isFlatline = False
279
+
280
+
281
+ col1, col2 = st.columns([1, 1])
282
+ with col1:
283
+ save_button = st.button(label="Save Data")
284
+ if save_button:
285
+ st.session_state.veltest_velocity = np.copy(st.session_state.dummyvelocity)
286
+ st.session_state.velocity_mask = np.copy(st.session_state.maskd)
287
+ st.session_state.isVelocityMask = True
288
+ st.write(":green[Mask data saved]")
289
+ else:
290
+ st.write(":red[Data not saved]")
291
+
292
+ with col2:
293
+ st.button(label="Reset Data", on_click=reset_data)