pyadps 0.1.0b0__py3-none-any.whl → 0.2.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.
@@ -110,6 +110,7 @@ if uploaded_file is not None:
110
110
  correlation = ds.correlation.data
111
111
  echo = ds.echo.data
112
112
  pgood = ds.percentgood.data
113
+ beamdir = ds.fixedleader.system_configuration()['Beam Direction']
113
114
 
114
115
  st.session_state.fname = uploaded_file.name
115
116
  st.session_state.head = ds.fileheader
@@ -119,6 +120,7 @@ if uploaded_file is not None:
119
120
  st.session_state.echo = ds.echo.data
120
121
  st.session_state.correlation = ds.correlation.data
121
122
  st.session_state.pgood = ds.percentgood.data
123
+ st.session_state.beam_direction = beamdir
122
124
 
123
125
  # st.session_state.flead = flead
124
126
  # st.session_state.vlead = vlead
@@ -46,24 +46,27 @@ def read_file(filepath):
46
46
  st.session_state.ds = ds
47
47
 
48
48
  @st.cache_data
49
- def file_write(path, add_attributes=True):
49
+ def file_write(path, axis_option, add_attributes=True):
50
50
  tempdirname = tempfile.TemporaryDirectory(delete=False)
51
51
  st.session_state.rawfilename = tempdirname.name + "/rawfile.nc"
52
52
 
53
53
  if add_attributes:
54
- wr.main(path, st.session_state.rawfilename, attributes=st.session_state.attributes)
54
+ wr.rawnc(path, st.session_state.rawfilename, st.session_state.date, axis_option, attributes=st.session_state.attributes)
55
55
  else:
56
- wr.main(path, st.session_state.rawfilename)
56
+ wr.rawnc(path, st.session_state.rawfilename, st.session_state.date,axis_option)
57
57
 
58
58
  @st.cache_data
59
- def file_write_vlead(path, add_attributes=True):
59
+ def file_write_vlead(path, axis_option, add_attributes=True):
60
60
  tempvardirname = tempfile.TemporaryDirectory(delete=False)
61
61
  st.session_state.vleadfilename = tempvardirname.name + "/vlead.nc"
62
62
 
63
63
  if add_attributes:
64
- wr.vlead_nc(path, st.session_state.vleadfilename, attributes=st.session_state.attributes)
64
+ wr.vlead_nc(path, st.session_state.vleadfilename, st.session_state.date, axis_option, attributes=st.session_state.attributes)
65
65
  else:
66
- wr.vlead_nc(path, st.session_state.vleadfilename)
66
+ wr.vlead_nc(path, st.session_state.vleadfilename, st.session_state.date, axis_option)
67
+
68
+ if "axis_option" not in st.session_state:
69
+ st.session_state.axis_option = "ensemble" # Default value
67
70
 
68
71
  # UI for attribute selection
69
72
  st.header("NetCDF File", divider="blue")
@@ -97,13 +100,23 @@ if add_attributes == "Yes":
97
100
  st.session_state.attributes['Comments'] = st.text_area("Comments")
98
101
 
99
102
  st.write("Attributes will be added to the NetCDF file once you submit.")
100
-
103
+
104
+ # Dropdown for axis_option
105
+ axis_option = st.selectbox(
106
+ "Select x-axis option:",
107
+ options=["ensemble", "time"],
108
+ index=0 # Default to "ensemble"
109
+ )
110
+
111
+ # Ensure it is passed correctly
112
+ st.session_state.axis_option = axis_option
113
+
101
114
  # Buttons to generate files
102
115
  download_button = st.button("Generate Raw NetCDF File")
103
116
  download_var_button = st.button("Generate Raw Variable Leader NetCDF File")
104
117
 
105
118
  if download_button:
106
- file_write(st.session_state.fpath, add_attributes == "Yes")
119
+ file_write(st.session_state.fpath, st.session_state.axis_option , add_attributes == "Yes")
107
120
  st.write(st.session_state.rawfilename)
108
121
  with open(st.session_state.rawfilename, "rb") as file:
109
122
  st.download_button(
@@ -113,7 +126,7 @@ if download_button:
113
126
  )
114
127
 
115
128
  if download_var_button:
116
- file_write_vlead(st.session_state.fpath, add_attributes == "Yes")
129
+ file_write_vlead(st.session_state.fpath, st.session_state.axis_option, add_attributes == "Yes")
117
130
  st.write(st.session_state.vleadfilename)
118
131
  with open(st.session_state.vleadfilename, "rb") as file:
119
132
  st.download_button(
@@ -5,6 +5,7 @@ import plotly.graph_objects as go
5
5
  import streamlit as st
6
6
  from plotly.subplots import make_subplots
7
7
  from plotly_resampler import FigureResampler
8
+ from streamlit.runtime.state import session_state
8
9
  from utils.signal_quality import ev_check, false_target, pg_check, qc_check
9
10
 
10
11
  if "flead" not in st.session_state:
@@ -134,11 +135,25 @@ plot_noise(dep=dn, rec=rn)
134
135
  ################## QC Test ###################
135
136
 
136
137
  st.header("Quality Control Tests", divider="blue")
138
+ st.write("")
137
139
 
138
140
  left, right = st.columns([1, 1])
139
141
  with left:
140
- st.write("Thresholds used during deployment")
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.""")
141
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:]")
142
157
  thresh = pd.DataFrame(
143
158
  [
144
159
  ["Correlation", fdata["Correlation Thresh"]],
@@ -222,7 +237,7 @@ with left:
222
237
  st.session_state.mask = mask
223
238
 
224
239
  if st.session_state.isThresh:
225
- st.write("Current Thresholds")
240
+ st.write(":green-background[Current Thresholds]")
226
241
  st.write(st.session_state.newthresh)
227
242
 
228
243
 
@@ -237,7 +252,7 @@ Ensure to save any necessary changes or apply additional thresholds if needed.
237
252
 
238
253
 
239
254
  if st.button("Display mask file"):
240
- st.header("Default Mask File", divider="blue")
255
+ st.subheader("Default Mask File")
241
256
  st.write(
242
257
  """
243
258
  ADCP assigns missing values based on thresholds set before deployment.
@@ -247,7 +262,7 @@ These values cannot be recovered and the default
247
262
  fillplot_plotly(st.session_state.orig_mask, colorscale="greys")
248
263
 
249
264
 
250
- st.header("Update Mask File", divider="blue")
265
+ st.subheader("Update Mask File")
251
266
  st.write(
252
267
  """
253
268
  Update, display and save the updated mask file after applying threshold.
@@ -257,8 +272,36 @@ If thresholds are not saved, default mask file is used.
257
272
  # values, counts = np.unique(mask, return_counts=True)
258
273
  fillplot_plotly(st.session_state.mask, colorscale="greys")
259
274
 
260
- col1, col2 = st.columns([1, 1])
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
+
261
299
 
300
+
301
+
302
+ ################## Save Button #############
303
+ st.header("Save Data", divider="blue")
304
+ col1, col2 = st.columns([1, 1])
262
305
  with col1:
263
306
  save_mask_button = st.button(label="Save Mask Data")
264
307
 
@@ -281,3 +324,11 @@ with col2:
281
324
  st.session_state.isProfileMask = False
282
325
  st.session_state.isVelocityMask = False
283
326
  st.write(":green[Mask data is reset to default]")
327
+
328
+
329
+
330
+
331
+
332
+
333
+
334
+
@@ -5,7 +5,7 @@ import plotly.graph_objects as go
5
5
  import streamlit as st
6
6
  from plotly.subplots import make_subplots
7
7
  from plotly_resampler import FigureResampler
8
- from utils.profile_test import side_lobe_beam_angle
8
+ from utils.profile_test import side_lobe_beam_angle, manual_cut_bins
9
9
  from utils.regrid import regrid2d, regrid3d
10
10
  from utils.signal_quality import default_mask
11
11
 
@@ -79,6 +79,7 @@ def fillplot_plotly(
79
79
  data, title="data", maskdata=None, missing=-32768, colorscale="balance"
80
80
  ):
81
81
  fig = FigureResampler(go.Figure())
82
+ data = np.int32(data)
82
83
  data1 = np.where(data == missing, np.nan, data)
83
84
  fig.add_trace(
84
85
  go.Heatmap(
@@ -98,7 +99,7 @@ def fillplot_plotly(
98
99
  colorscale="gray",
99
100
  hoverongaps=False,
100
101
  showscale=False,
101
- opacity=0.5,
102
+ opacity=0.7,
102
103
  )
103
104
  )
104
105
  fig.update_layout(
@@ -113,6 +114,7 @@ def fillplot_plotly(
113
114
 
114
115
  def fillselect_plotly(data, title="data", colorscale="balance"):
115
116
  fig = FigureResampler(go.Figure())
117
+ data = np.int32(data)
116
118
  data1 = np.where(data == -32768, None, data)
117
119
  fig.add_trace(
118
120
  go.Heatmap(
@@ -215,8 +217,10 @@ m = 20
215
217
  if "update_mask" not in st.session_state:
216
218
  st.session_state.update_mask = False
217
219
  st.session_state.endpoints = None
220
+ st.session_state.isTrimEnds = False
218
221
  if "update_mask_cutbin" not in st.session_state:
219
222
  st.session_state.update_mask_cutbin = False
223
+ st.session_state.isCutBins = False
220
224
 
221
225
  ens_range = st.number_input("Change range", x[0], x[-1], 20)
222
226
  start_ens = st.slider("Deployment Ensembles", 0, ens_range, 0)
@@ -226,7 +230,7 @@ n = int(ens_range)
226
230
 
227
231
  if start_ens or end_ens:
228
232
  trim_ends(start_ens=start_ens, end_ens=end_ens, ens_range=n)
229
- st.session_state.update_mask = False
233
+ # st.session_state.update_mask = False
230
234
 
231
235
  update_mask = st.button("Update mask data")
232
236
  if update_mask:
@@ -246,6 +250,7 @@ if update_mask:
246
250
  )
247
251
  st.write(st.session_state.endpoints)
248
252
  st.session_state.update_mask = True
253
+ st.session_state.isTrimEnds = True
249
254
 
250
255
  if not st.session_state.update_mask:
251
256
  st.write(":red[mask data not updated]")
@@ -268,13 +273,22 @@ beam = beam - 1
268
273
  st.session_state.beam = beam
269
274
  fillplot_plotly(echo[beam, :, :], title="Echo Intensity")
270
275
 
276
+ orientation = st.session_state.beam_direction
277
+ st.write(f"The orientation is `{orientation}`.")
278
+ water_column_depth = 0
271
279
  with st.form(key="cutbin_form"):
272
280
  extra_cells = st.number_input("Additional Cells to Delete", 0, 10, 0)
281
+ if orientation.lower() == 'down':
282
+ water_column_depth = st.number_input("Enter water column depth (m): ", 0, 15000, 0)
283
+
273
284
  cut_bins_mask = st.form_submit_button(label="Cut bins")
274
285
 
275
286
  if cut_bins_mask:
276
287
  st.session_state.extra_cells = extra_cells
277
- mask = side_lobe_beam_angle(flobj, vlobj, mask, extra_cells=extra_cells)
288
+ mask = side_lobe_beam_angle(flobj, vlobj, mask,
289
+ orientation=orientation,
290
+ water_column_depth=water_column_depth,
291
+ extra_cells=extra_cells)
278
292
  fillplot_plotly(
279
293
  echo[beam, :, :],
280
294
  title="Echo Intensity (Masked)",
@@ -287,14 +301,140 @@ if update_mask_cutbin:
287
301
  st.session_state.maskp = mask
288
302
  st.write(":green[mask file updated]")
289
303
  st.session_state.update_mask_cutbin = True
304
+ st.session_state.isCutBins = True
290
305
 
291
306
  if not st.session_state.update_mask_cutbin:
292
307
  st.write(":red[mask file not updated]")
293
308
 
294
309
 
295
- ############ CUT BINS: Manual #################
310
+ ########### CUT BINS: Manual #################
296
311
  st.header("Cut Bins: Manual", divider="blue")
312
+ # Reset mask
313
+ # Selection of variable (Velocity, Echo Intensity, etc.)
314
+ variable = st.selectbox(
315
+ "Select Variable to Display",
316
+ ("Velocity", "Echo Intensity", "Correlation", "Percentage Good")
317
+ )
318
+
319
+ # Map variable selection to corresponding data
320
+ data_dict = {
321
+ "Velocity": velocity,
322
+ "Echo Intensity": echo,
323
+ "Correlation": correlation,
324
+ "Percentage Good": pgood,
325
+ }
326
+
327
+ # User selects beam (1-4)
328
+ beam = st.radio("Select beam", (1, 2, 3, 4), horizontal=True, key="beam_selection")
329
+ beam_index = beam - 1
330
+
331
+ # Display the selected variable and beam
332
+ selected_data = data_dict[variable][beam_index, :, :]
333
+ fillplot_plotly(selected_data, title=f"{variable}")
334
+
335
+
336
+ st.subheader("Mask Selected Regions")
337
+ with st.form(key="manual_cutbin_form"):
338
+ st.write("Select the specific range of cells and ensembles to delete")
339
+
340
+ # Input for selecting minimum and maximum cells
341
+ min_cell = st.number_input("Min Cell", 0, int(flobj.field()["Cells"]), 0)
342
+ max_cell = st.number_input("Max Cell", 0, int(flobj.field()["Cells"]), 10)
343
+
344
+ # Input for selecting minimum and maximum ensembles
345
+ min_ensemble = st.number_input("Min Ensemble", 0, int(flobj.ensembles), 0)
346
+ max_ensemble = st.number_input("Max Ensemble", 0, int(flobj.ensembles), int(flobj.ensembles))
347
+
348
+ # Submit button to apply the mask
349
+ cut_bins_mask_manual = st.form_submit_button(label="Apply Manual Cut Bins")
297
350
 
351
+ if cut_bins_mask_manual:
352
+ mask = manual_cut_bins(mask, min_cell, max_cell, min_ensemble, max_ensemble)
353
+ st.session_state.maskp = mask
354
+ fillplot_plotly(
355
+ echo[beam, :, :],
356
+ title="Echo Intensity (Masked Manually)",
357
+ maskdata=mask,
358
+ )
359
+ fillplot_plotly(mask, colorscale="greys", title="Mask Data")
360
+
361
+ # Adding the new feature: Delete Single Cell or Ensemble
362
+ st.subheader("Delete Specific Cell or Ensemble")
363
+
364
+ # Step 1: User chooses between deleting a cell or an ensemble
365
+ delete_option = st.radio("Select option to delete", ("Cell", "Ensemble"), horizontal=True)
366
+
367
+ # Step 2: Display options based on user's choice
368
+ if delete_option == "Cell":
369
+ # Option to delete a specific cell across all ensembles
370
+ with st.form(key="delete_cell_form"):
371
+ st.write("Select a specific cell to delete across all ensembles")
372
+
373
+ # Input for selecting a single cell
374
+ cell = st.number_input("Cell", 0, int(flobj.field()["Cells"]), 0, key="single_cell")
375
+
376
+ # Submit button to apply the mask for cell deletion
377
+ delete_cell = st.form_submit_button(label="Delete Cell")
378
+
379
+ if delete_cell:
380
+ mask[cell, :] = 1 # Mask the entire row for the selected cell
381
+ st.session_state.maskp = mask
382
+ fillplot_plotly(
383
+ echo[beam, :, :],
384
+ title=f"Echo Intensity (Cell {cell} Deleted Across Ensembles)",
385
+ maskdata=mask,
386
+ )
387
+ fillplot_plotly(mask, colorscale="greys", title="Mask Data")
388
+
389
+ elif delete_option == "Ensemble":
390
+ # Option to delete a specific ensemble across all cells
391
+ with st.form(key="delete_ensemble_form"):
392
+ st.write("Select a specific ensemble to delete across all cells")
393
+
394
+ # Input for selecting a specific ensemble
395
+ ensemble = st.number_input("Ensemble", 0, int(flobj.ensembles), 0, key="single_ensemble")
396
+
397
+ # Submit button to apply the mask for ensemble deletion
398
+ delete_ensemble = st.form_submit_button(label="Delete Ensemble")
399
+
400
+ if delete_ensemble:
401
+ mask[:, ensemble-1] = 1 # Mask the entire column for the selected ensemble
402
+ st.session_state.maskp = mask
403
+ fillplot_plotly(
404
+ echo[beam, :, :],
405
+ title=f"Echo Intensity (Ensemble {ensemble} Deleted Across Cells)",
406
+ maskdata=mask,
407
+ )
408
+ fillplot_plotly(mask, colorscale="greys", title="Mask Data")
409
+
410
+
411
+ # Layout with two columns
412
+ col1, col2 = st.columns([2, 1])
413
+
414
+ with col1:
415
+
416
+ # Button to save mask data after manual cut bins, with unique key
417
+ update_mask_cutbin = st.button("Update mask file after cutbin Manual", key="update_cutbin_button")
418
+ if update_mask_cutbin:
419
+ st.session_state.maskp = mask
420
+ st.write(":green[mask file updated]")
421
+ st.session_state.update_mask_cutbin = True
422
+ st.session_state.isCutBins = True
423
+
424
+ if not st.session_state.update_mask_cutbin:
425
+ st.write(":red[mask file not updated]")
426
+
427
+ with col2:
428
+ # Button to reset the mask data, with unique key
429
+ reset_mask_button = st.button("Reset mask data", key="reset_mask_button")
430
+ if reset_mask_button:
431
+ st.session_state.maskp = np.copy(st.session_state.orig_mask)
432
+ st.write(":green[Mask data is reset to default]")
433
+ st.session_state.isQCMask = False
434
+ st.session_state.isProfileMask = False
435
+ st.session_state.isGrid = False
436
+ st.session_state.isGridSave = False
437
+ st.session_state.isVelocityMask = False
298
438
 
299
439
  ############ REGRID ###########################################
300
440
  st.header("Regrid Depth Cells", divider="blue")
@@ -304,38 +444,84 @@ st.write(
304
444
  When the ADCP buoy has vertical oscillations (greater than depth cell size),
305
445
  the depth bins has to be regridded based on the pressure sensor data. The data
306
446
  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.
447
+ If the `Cell` option is selected, ensure that the end data are trimmed.
448
+ Manual option permits choosing the end cell depth.
308
449
  """
309
450
  )
310
451
 
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")
452
+ if st.session_state.beam_direction.lower() == "up":
453
+ end_bin_option = st.radio(
454
+ "Select the depth of last bin for regridding", ("Cell", "Surface", "Manual"), horizontal=True
455
+ )
456
+ else:
457
+ end_bin_option = st.radio(
458
+ "Select the depth of last bin for regridding", ("Cell", "Manual"), horizontal=True
459
+ )
460
+
461
+ st.session_state.end_bin_option = end_bin_option
462
+ st.write(f"You have selected: `{end_bin_option}`")
463
+
464
+ if end_bin_option == "Manual":
465
+ mean_depth = np.mean(st.session_state.vlead.vleader["Depth of Transducer"]) / 10
466
+ mean_depth = round(mean_depth, 2)
317
467
 
468
+ st.write(f"The transducer depth is {mean_depth} m. The value should not exceed the transducer depth")
469
+ if st.session_state.beam_direction.lower() == "up":
470
+ boundary = st.number_input("Enter the depth (m):", max_value=int(mean_depth), min_value=0)
471
+ else:
472
+ boundary = st.number_input("Enter the depth (m):", min_value=int(mean_depth))
473
+ else:
474
+ boundary = 0
475
+
476
+ interpolate = st.radio("Choose interpolation method:", ("nearest", "linear", "cubic"))
477
+
478
+ regrid_button = st.button(label="Regrid Data")
318
479
 
319
480
  if regrid_button:
320
481
  st.write(st.session_state.endpoints)
321
482
  z, st.session_state.velocity_regrid = regrid3d(
322
- flobj, vlobj, velocity, -32768, trimends=st.session_state.endpoints
483
+ flobj, vlobj, velocity, -32768,
484
+ trimends=st.session_state.endpoints,
485
+ end_bin_option=st.session_state.end_bin_option,
486
+ orientation=st.session_state.beam_direction,
487
+ method=interpolate,
488
+ boundary_limit=boundary
323
489
  )
324
490
  st.write(":grey[Regrided velocity ...]")
325
491
  z, st.session_state.echo_regrid = regrid3d(
326
- flobj, vlobj, echo, -32768, trimends=st.session_state.endpoints
492
+ flobj, vlobj, echo, -32768,
493
+ trimends=st.session_state.endpoints,
494
+ end_bin_option=st.session_state.end_bin_option,
495
+ orientation=st.session_state.beam_direction,
496
+ method=interpolate,
497
+ boundary_limit=boundary
327
498
  )
328
499
  st.write(":grey[Regrided echo intensity ...]")
329
500
  z, st.session_state.correlation_regrid = regrid3d(
330
- flobj, vlobj, correlation, -32768, trimends=st.session_state.endpoints
501
+ flobj, vlobj, correlation, -32768,
502
+ trimends=st.session_state.endpoints,
503
+ end_bin_option=st.session_state.end_bin_option,
504
+ orientation=st.session_state.beam_direction,
505
+ method=interpolate,
506
+ boundary_limit=boundary
331
507
  )
332
508
  st.write(":grey[Regrided correlation...]")
333
509
  z, st.session_state.pgood_regrid = regrid3d(
334
- flobj, vlobj, pgood, -32768, trimends=st.session_state.endpoints
510
+ flobj, vlobj, pgood, -32768,
511
+ trimends=st.session_state.endpoints,
512
+ end_bin_option=st.session_state.end_bin_option,
513
+ orientation=st.session_state.beam_direction,
514
+ method=interpolate,
515
+ boundary_limit=boundary
335
516
  )
336
517
  st.write(":grey[Regrided percent good...]")
337
518
  z, st.session_state.mask_regrid = regrid2d(
338
- flobj, vlobj, mask, 1, trimends=st.session_state.endpoints
519
+ flobj, vlobj, mask, 1,
520
+ trimends=st.session_state.endpoints,
521
+ end_bin_option=st.session_state.end_bin_option,
522
+ orientation=st.session_state.beam_direction,
523
+ method="nearest",
524
+ boundary_limit=boundary
339
525
  )
340
526
 
341
527
  st.session_state.depth = z
@@ -9,7 +9,7 @@ from streamlit.runtime.state import session_state
9
9
  from utils.profile_test import side_lobe_beam_angle
10
10
  from utils.signal_quality import default_mask
11
11
  from utils.velocity_test import (despike, flatline, magnetic_declination,
12
- velocity_cutoff)
12
+ velocity_cutoff, wmm2020api, velocity_modifier)
13
13
 
14
14
  if "flead" not in st.session_state:
15
15
  st.write(":red[Please Select Data!]")
@@ -104,12 +104,24 @@ The processing in this page apply only to the velocity data.
104
104
  st.header("Magnetic Declination", divider="blue")
105
105
  st.write(
106
106
  """
107
- The magnetic declination is obtained from World Magnetic Model 2020 (WMM2020).
107
+ * The magnetic declination is obtained from World Magnetic Model 2020 (WMM2020).
108
108
  The python wrapper module `wmm2020` is available from this [Link](https://github.com/space-physics/wmm2020).
109
+
110
+ * The API method utilizes the online magnetic declination service provided by the National Geophysical Data Center (NGDC)
111
+ 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).
112
+ Internet connection is necessary for this method to work.
113
+
114
+ * In the manual method, the user can directly enter the magnetic declination.
115
+
109
116
  If the magnetic declination is reset, re-run the remaining tests again.
110
117
  """
111
118
  )
112
119
 
120
+ # Selecting the method to calculate magnetic declination.
121
+ method = st.radio("Select a method", ("WMM2020", "API", "Manual"), horizontal=True)
122
+ # method = method - 1
123
+ st.session_state.method = method
124
+
113
125
  if "isMagnetButton" not in st.session_state:
114
126
  st.session_state.isMagnetButton = False
115
127
 
@@ -119,23 +131,60 @@ def toggle_btns():
119
131
 
120
132
 
121
133
  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)
134
+ if st.session_state.method == "WMM2020":
135
+ st.session_state.isMagnet = False
136
+ lat = st.number_input("Latitude", -90.0, 90.0, 0.0, step=1.0)
137
+ lon = st.number_input("Longitude", 0.0, 360.0, 0.1, step=1.0, format="%.4f")
138
+ depth = st.number_input("Depth", 0, 1000, 0, step=1)
139
+ year = st.number_input("Year", 1950, 2100, 2024, 1)
140
+ elif st.session_state.method == "API":
141
+ st.session_state.isMagnet = False
142
+ lat = st.number_input("Latitude", -90.0, 90.0, 0.0, step=1.0)
143
+ lon = st.number_input("Longitude", 0.0, 360.0, 0.1, step=1.0, format="%.4f")
144
+ year = st.number_input("Year", 1950, 2100, 2024, 1)
145
+ else:
146
+ st.session_state.isMagnet = False
147
+ mag = [[st.number_input("Declination", -180.0, 180.0, 0.0, 0.1)]]
148
+
149
+ if st.session_state.method == "Manual":
150
+ button_name = "Accept"
151
+ else:
152
+ button_name = "Compute"
153
+
126
154
 
127
155
  if st.form_submit_button(
128
- "Compute", on_click=toggle_btns, disabled=st.session_state.isMagnetButton
156
+ button_name, on_click=toggle_btns, disabled=st.session_state.isMagnetButton
129
157
  ):
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
158
+ if st.session_state.method == "WMM2020":
159
+ try:
160
+ mag = magnetic_declination(lat, lon, depth, year)
161
+ st.session_state.dummyvelocity = velocity_modifier(velocity, mag)
162
+ st.session_state.lat = lat
163
+ st.session_state.lon = lon
164
+ st.session_state.magnetic_dec_depth = depth
165
+ st.session_state.year = year
166
+ st.session_state.angle = np.trunc(mag[0][0])
167
+ st.session_state.isMagnet = True
168
+ except:
169
+ st.write(":red[Process failed! please use other methods: API or Manual]")
170
+
171
+ elif st.session_state.method == "API":
172
+ try:
173
+ mag = wmm2020api(lat, lon, year)
174
+ st.session_state.dummyvelocity = velocity_modifier(velocity, mag)
175
+ st.session_state.lat = lat
176
+ st.session_state.lon = lon
177
+ st.session_state.year = year
178
+ st.session_state.angle = np.trunc(mag[0][0])
179
+ st.session_state.isMagnet = True
180
+ except:
181
+ st.write(":red[Connection error! please check the internet or use other methods: WMM2020 or Manual]")
182
+
183
+ else:
184
+ st.session_state.dummyvelocity = velocity_modifier(velocity, mag)
185
+ st.session_state.angle = np.trunc(mag[0][0])
186
+ st.session_state.isMagnet = True
187
+
139
188
 
140
189
  if st.session_state.isMagnet:
141
190
  st.write(f"Magnetic declination: {st.session_state.angle}\u00b0")
@@ -170,7 +219,6 @@ if submit_cutoff:
170
219
  st.session_state.maxvvel = maxvvel
171
220
  st.session_state.maxwvel = maxwvel
172
221
 
173
-
174
222
  st.session_state.maskd = velocity_cutoff(
175
223
  velocity[0, :, :], st.session_state.maskd, cutoff=maxuvel
176
224
  )
@@ -184,7 +232,7 @@ if submit_cutoff:
184
232
 
185
233
 
186
234
  if st.session_state.isCutoff:
187
- st.write("Cutoff Applied")
235
+ st.write(":green[Cutoff Applied]")
188
236
  a = {
189
237
  "Max. Zonal Velocity": maxuvel,
190
238
  "Max. Meridional Velocity": maxvvel,
@@ -220,7 +268,7 @@ if despike_button:
220
268
  st.session_state.isDespike = True
221
269
 
222
270
  if st.session_state.isDespike:
223
- st.write("Data Despiked")
271
+ st.write(":green[Data Despiked]")
224
272
  b = {
225
273
  "Kernal Size": despike_kernal,
226
274
  "Despike Cutoff": despike_cutoff,