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.
Files changed (39) hide show
  1. pyadps/Home_Page.py +11 -5
  2. pyadps/pages/01_Read_File.py +623 -215
  3. pyadps/pages/02_View_Raw_Data.py +97 -41
  4. pyadps/pages/03_Download_Raw_File.py +200 -67
  5. pyadps/pages/04_Sensor_Health.py +905 -0
  6. pyadps/pages/05_QC_Test.py +493 -0
  7. pyadps/pages/06_Profile_Test.py +971 -0
  8. pyadps/pages/07_Velocity_Test.py +600 -0
  9. pyadps/pages/08_Write_File.py +623 -0
  10. pyadps/pages/09_Add-Ons.py +168 -0
  11. pyadps/utils/__init__.py +5 -3
  12. pyadps/utils/autoprocess.py +371 -80
  13. pyadps/utils/logging_utils.py +269 -0
  14. pyadps/utils/metadata/config.ini +22 -4
  15. pyadps/utils/metadata/demo.000 +0 -0
  16. pyadps/utils/metadata/flmeta.json +420 -420
  17. pyadps/utils/metadata/vlmeta.json +611 -565
  18. pyadps/utils/multifile.py +292 -0
  19. pyadps/utils/plotgen.py +505 -3
  20. pyadps/utils/profile_test.py +720 -125
  21. pyadps/utils/pyreadrdi.py +164 -92
  22. pyadps/utils/readrdi.py +436 -186
  23. pyadps/utils/script.py +197 -147
  24. pyadps/utils/sensor_health.py +120 -0
  25. pyadps/utils/signal_quality.py +472 -68
  26. pyadps/utils/velocity_test.py +79 -31
  27. pyadps/utils/writenc.py +222 -39
  28. {pyadps-0.2.1b0.dist-info → pyadps-0.3.0.dist-info}/METADATA +13 -14
  29. pyadps-0.3.0.dist-info/RECORD +35 -0
  30. {pyadps-0.2.1b0.dist-info → pyadps-0.3.0.dist-info}/WHEEL +1 -1
  31. {pyadps-0.2.1b0.dist-info → pyadps-0.3.0.dist-info}/entry_points.txt +1 -0
  32. pyadps/pages/04_QC_Test.py +0 -334
  33. pyadps/pages/05_Profile_Test.py +0 -575
  34. pyadps/pages/06_Velocity_Test.py +0 -341
  35. pyadps/pages/07_Write_File.py +0 -452
  36. pyadps/utils/cutbin.py +0 -413
  37. pyadps/utils/regrid.py +0 -279
  38. pyadps-0.2.1b0.dist-info/RECORD +0 -31
  39. {pyadps-0.2.1b0.dist-info → pyadps-0.3.0.dist-info}/LICENSE +0 -0
@@ -0,0 +1,623 @@
1
+ import configparser
2
+ import tempfile
3
+ import os
4
+ import numpy as np
5
+ import pandas as pd
6
+ import plotly.graph_objects as go
7
+ import streamlit as st
8
+ import utils.writenc as wr
9
+ from plotly_resampler import FigureResampler
10
+
11
+ if "flead" not in st.session_state:
12
+ st.write(":red[Please Select Data!]")
13
+ st.stop()
14
+
15
+ if "fname" not in st.session_state:
16
+ st.session_state.fname = "No file selected"
17
+
18
+ if "rawfilename" not in st.session_state:
19
+ st.session_state.rawfilename = "RAW_DAT.nc"
20
+
21
+ if "vleadfilename" not in st.session_state:
22
+ st.session_state.vleadfilename = "RAW_VAR.nc"
23
+
24
+ if "file_prefix" not in st.session_state:
25
+ raw_basename = os.path.basename(st.session_state.fname)
26
+ st.session_state.filename = os.path.splitext(raw_basename)[0]
27
+ st.session_state.file_prefix = st.session_state.filename
28
+
29
+
30
+ if "prefix_saved" not in st.session_state:
31
+ st.session_state.prefix_saved = False
32
+
33
+ if "filename" not in st.session_state:
34
+ st.session_state.filename = "" # <-- Default file name if not passed
35
+
36
+
37
+ # Check if attributes exist in session state
38
+ if "attributes" not in st.session_state:
39
+ st.session_state.attributes = {}
40
+ st.session_state.isAttributes = False
41
+
42
+ if st.session_state.isVelocityTest:
43
+ st.session_state.final_mask = st.session_state.velocity_mask
44
+
45
+ if st.session_state.isVelocityModifiedMagnet:
46
+ st.session_state.final_velocity = st.session_state.velocity_magnet
47
+ if st.session_state.isRegridCheck_PT:
48
+ st.session_state.final_velocity = st.session_state.velocity_regrid
49
+ elif st.session_state.isVelocityModifiedSound_ST:
50
+ st.session_state.final_velocity = st.session_state.velocity_sensor
51
+ else:
52
+ st.session_state.final_velocity = st.session_state.velocity
53
+
54
+ if st.session_state.isRegridCheck_PT:
55
+ st.session_state.final_echo = st.session_state.echo_regrid
56
+ st.session_state.final_correlation = st.session_state.correlation_regrid
57
+ st.session_state.final_pgood = st.session_state.pgood_regrid
58
+ else:
59
+ st.session_state.final_echo = st.session_state.echo
60
+ st.session_state.final_correlation = st.session_state.correlation
61
+ st.session_state.final_pgood = st.session_state.pgood
62
+ else:
63
+ if st.session_state.isRegridCheck_PT:
64
+ st.session_state.final_mask = st.session_state.profile_mask_regrid
65
+ st.session_state.final_velocity = st.session_state.velocity_regrid
66
+ st.session_state.final_echo = st.session_state.echo_regrid
67
+ st.session_state.final_correlation = st.session_state.correlation_regrid
68
+ st.session_state.final_pgood = st.session_state.pgood_regrid
69
+ else:
70
+ if st.session_state.isProfileTest:
71
+ st.session_state.final_mask = st.session_state.profile_mask
72
+ elif st.session_state.isQCTest:
73
+ st.session_state.final_mask = st.session_state.qc_mask
74
+ elif st.session_state.isSensorTest:
75
+ st.session_state.final_mask = st.session_state.sensor_mask
76
+ else:
77
+ st.session_state.final_mask = st.session_state.orig_mask
78
+ st.session_state.final_velocity = st.session_state.velocity
79
+ st.session_state.final_echo = st.session_state.echo
80
+ st.session_state.final_correlation = st.session_state.correlation
81
+ st.session_state.final_pgood = st.session_state.pgood
82
+
83
+
84
+ if "depth_axis" not in st.session_state:
85
+ st.session_state.isRegridCheck_PT = False
86
+
87
+
88
+ @st.cache_data
89
+ def get_prefixed_filename(base_name):
90
+ """Generates the file name with the optional prefix."""
91
+ if st.session_state.file_prefix:
92
+ return f"{st.session_state.file_prefix}_{base_name}"
93
+ return base_name
94
+
95
+
96
+ @st.cache_data
97
+ def file_write(filename=get_prefixed_filename("PRO_DAT.nc")):
98
+ tempdirname = tempfile.TemporaryDirectory(delete=False)
99
+ outfilepath = tempdirname.name + "/" + filename
100
+ return outfilepath
101
+
102
+
103
+ # If the data is not regrided based on pressure sensor. Use the mean depth
104
+ if not st.session_state.isRegridCheck_PT:
105
+ st.write(":red[WARNING!]")
106
+ st.write(
107
+ "Data not regrided. Using the mean transducer depth to calculate the depth axis."
108
+ )
109
+ # mean_depth = np.mean(st.session_state.vlead.vleader["Depth of Transducer"]) / 10
110
+ mean_depth = np.mean(st.session_state.depth) / 10
111
+ mean_depth = np.trunc(mean_depth)
112
+ st.write(f"Mean depth of the transducer is `{mean_depth}`")
113
+ cells = st.session_state.flead.field()["Cells"]
114
+ cell_size = st.session_state.flead.field()["Depth Cell Len"] / 100
115
+ bin1dist = st.session_state.flead.field()["Bin 1 Dist"] / 100
116
+ if st.session_state.beam_direction_QCT.lower() == "up":
117
+ sgn = -1
118
+ else:
119
+ sgn = 1
120
+ first_depth = mean_depth + sgn * bin1dist
121
+ last_depth = first_depth + sgn * cells * cell_size
122
+ z = np.arange(first_depth, last_depth, sgn * cell_size)
123
+ st.session_state.final_depth_axis = z
124
+ else:
125
+ st.session_state.final_depth_axis = st.session_state.depth_axis
126
+
127
+
128
+ # Functions for plotting
129
+ @st.cache_data
130
+ def fillplot_plotly(
131
+ x, y, data, maskdata, colorscale="balance", title="Data", mask=False
132
+ ):
133
+ fig = FigureResampler(go.Figure())
134
+ if mask:
135
+ data1 = np.where(maskdata == 1, np.nan, data)
136
+ else:
137
+ data1 = np.where(data == -32768, np.nan, data)
138
+
139
+ fig.add_trace(
140
+ go.Heatmap(
141
+ z=data1[:, 0:-1],
142
+ x=x,
143
+ y=y,
144
+ colorscale=colorscale,
145
+ hoverongaps=False,
146
+ )
147
+ )
148
+ fig.update_layout(
149
+ xaxis=dict(showline=True, mirror=True),
150
+ yaxis=dict(showline=True, mirror=True),
151
+ title_text=title,
152
+ )
153
+ fig.update_yaxes(autorange="reversed")
154
+ st.plotly_chart(fig)
155
+
156
+
157
+ def call_plot(varname, beam, mask=False):
158
+ if varname == "Velocity":
159
+ fillplot_plotly(
160
+ st.session_state.date,
161
+ st.session_state.final_depth_axis,
162
+ st.session_state.final_velocity[beam - 1, :, :],
163
+ st.session_state.final_mask,
164
+ title=varname,
165
+ mask=mask,
166
+ )
167
+ elif varname == "Echo":
168
+ fillplot_plotly(
169
+ st.session_state.date,
170
+ st.session_state.final_depth_axis,
171
+ st.session_state.final_echo[beam - 1, :, :],
172
+ st.session_state.final_mask,
173
+ title=varname,
174
+ mask=mask,
175
+ )
176
+ elif varname == "Correlation":
177
+ fillplot_plotly(
178
+ st.session_state.date,
179
+ st.session_state.final_depth_axis,
180
+ st.session_state.final_correlation[beam - 1, :, :],
181
+ st.session_state.final_mask,
182
+ title=varname,
183
+ mask=mask,
184
+ )
185
+ elif varname == "Percent Good":
186
+ fillplot_plotly(
187
+ st.session_state.date,
188
+ st.session_state.final_depth_axis,
189
+ st.session_state.final_pgood[beam - 1, :, :],
190
+ st.session_state.final_mask,
191
+ title=varname,
192
+ mask=mask,
193
+ )
194
+
195
+
196
+ # Option to View Processed Data
197
+ st.header("View Processed Data", divider="blue")
198
+ var_option = st.selectbox(
199
+ "Select a data type", ("Velocity", "Echo", "Correlation", "Percent Good")
200
+ )
201
+ beam = st.radio("Select beam", (1, 2, 3, 4), horizontal=True)
202
+
203
+ mask_radio = st.radio("Apply Mask", ("Yes", "No"), horizontal=True)
204
+ plot_button = st.button("Plot Processed Data")
205
+ if plot_button:
206
+ if mask_radio == "Yes":
207
+ call_plot(var_option, beam, mask=True)
208
+ elif mask_radio == "No":
209
+ call_plot(var_option, beam, mask=False)
210
+
211
+
212
+ # Option to Write Processed Data
213
+ st.header("Write Data", divider="blue")
214
+
215
+ st.session_state.mask_data_WF = st.radio(
216
+ "Do you want to mask the final data?", ("Yes", "No")
217
+ )
218
+
219
+ if st.session_state.mask_data_WF == "Yes":
220
+ mask = st.session_state.final_mask
221
+ st.session_state.write_velocity = np.copy(st.session_state.final_velocity).astype(
222
+ np.int16
223
+ )
224
+ st.session_state.write_velocity[:, mask == 1] = -32768
225
+
226
+ else:
227
+ st.session_state.write_velocity = np.copy(st.session_state.final_velocity)
228
+
229
+ st.session_state.file_type_WF = st.radio(
230
+ "Select output file format:", ("NetCDF", "CSV")
231
+ )
232
+
233
+ if st.session_state.file_type_WF == "NetCDF":
234
+ add_attr_button = st.checkbox("Add attributes to NetCDF file")
235
+
236
+ if add_attr_button:
237
+ st.session_state.isAttributes = True
238
+ st.write("### Modify Attributes")
239
+
240
+ # Create two-column layout for attributes
241
+ col1, col2 = st.columns(2)
242
+
243
+ with col1:
244
+ # Display attributes in the first column
245
+ for key in [
246
+ "Cruise_No.",
247
+ "Ship_Name",
248
+ "Project_No.",
249
+ "Water_Depth_m",
250
+ "Deployment_Depth_m",
251
+ "Deployment_Date",
252
+ "Recovery_Date",
253
+ ]:
254
+ if key in st.session_state.attributes:
255
+ st.session_state.attributes[key] = st.text_input(
256
+ key, value=st.session_state.attributes[key]
257
+ )
258
+ else:
259
+ st.session_state.attributes[key] = st.text_input(key)
260
+
261
+ with col2:
262
+ # Display attributes in the second column
263
+ for key in [
264
+ "Latitude",
265
+ "Longitude",
266
+ "Platform_Type",
267
+ "Participants",
268
+ "File_created_by",
269
+ "Contact",
270
+ "Comments",
271
+ ]:
272
+ if key in st.session_state.attributes:
273
+ st.session_state.attributes[key] = st.text_input(
274
+ key, value=st.session_state.attributes[key]
275
+ )
276
+ else:
277
+ st.session_state.attributes[key] = st.text_input(key)
278
+
279
+ download_button = st.button("Generate Processed files")
280
+
281
+ if download_button:
282
+ st.session_state.processed_filename = file_write()
283
+ st.write(":grey[Processed file created. Click the download button.]")
284
+ # st.write(st.session_state.processed_filename)
285
+ depth_axis = np.trunc(st.session_state.final_depth_axis)
286
+ final_mask = st.session_state.final_mask
287
+ st.session_state.write_echo = np.copy(st.session_state.final_echo)
288
+ st.session_state.write_correlation = np.copy(st.session_state.final_correlation)
289
+ st.session_state.write_pgood = np.copy(st.session_state.final_pgood)
290
+
291
+ if st.session_state.file_type_WF == "NetCDF":
292
+ if add_attr_button and st.session_state.attributes:
293
+ # Generate file with attributes
294
+ wr.finalnc(
295
+ st.session_state.processed_filename,
296
+ depth_axis,
297
+ final_mask,
298
+ st.session_state.write_echo,
299
+ st.session_state.write_correlation,
300
+ st.session_state.write_pgood,
301
+ st.session_state.date,
302
+ st.session_state.write_velocity,
303
+ attributes=st.session_state.attributes, # Pass edited attributes
304
+ )
305
+ else:
306
+ # Generate file without attributes
307
+ wr.finalnc(
308
+ st.session_state.processed_filename,
309
+ depth_axis,
310
+ final_mask,
311
+ st.session_state.write_echo,
312
+ st.session_state.write_correlation,
313
+ st.session_state.write_pgood,
314
+ st.session_state.date,
315
+ st.session_state.write_velocity,
316
+ )
317
+
318
+ with open(st.session_state.processed_filename, "rb") as file:
319
+ st.download_button(
320
+ label="Download NetCDF File",
321
+ data=file,
322
+ file_name=get_prefixed_filename("PRO_DAT.nc"),
323
+ )
324
+
325
+ if st.session_state.file_type_WF == "CSV":
326
+ udf = pd.DataFrame(
327
+ st.session_state.write_velocity[0, :, :].T,
328
+ index=st.session_state.date,
329
+ columns=-1 * depth_axis,
330
+ )
331
+ vdf = pd.DataFrame(
332
+ st.session_state.write_velocity[1, :, :].T,
333
+ index=st.session_state.date,
334
+ columns=-1 * depth_axis,
335
+ )
336
+ wdf = pd.DataFrame(
337
+ st.session_state.write_velocity[2, :, :].T,
338
+ index=st.session_state.date,
339
+ columns=-1 * depth_axis,
340
+ )
341
+ ucsv = udf.to_csv().encode("utf-8")
342
+ vcsv = vdf.to_csv().encode("utf-8")
343
+ wcsv = wdf.to_csv().encode("utf-8")
344
+ csv_mask = pd.DataFrame(st.session_state.final_mask.T).to_csv().encode("utf-8")
345
+ st.download_button(
346
+ label="Download Zonal Velocity File (CSV)",
347
+ data=ucsv,
348
+ file_name="zonal_velocity.csv",
349
+ mime="text/csf",
350
+ )
351
+ st.download_button(
352
+ label="Download Meridional Velocity File (CSV)",
353
+ data=vcsv,
354
+ file_name="meridional_velocity.csv",
355
+ mime="text/csf",
356
+ )
357
+ st.download_button(
358
+ label="Download Vertical Velocity File (CSV)",
359
+ data=vcsv,
360
+ file_name="vertical_velocity.csv",
361
+ mime="text/csf",
362
+ )
363
+
364
+ st.download_button(
365
+ label="Download Final Mask (CSV)",
366
+ data=csv_mask,
367
+ file_name="final_mask.csv",
368
+ mime="text/csv",
369
+ )
370
+
371
+
372
+ # Option to Download Config file
373
+ # ------------------------------
374
+
375
+ # Header for the Config.ini File Generator
376
+ st.header("Config.ini File Generator", divider="blue")
377
+
378
+ # Radio button to decide whether to generate the config.ini file
379
+ generate_config_radio = st.radio(
380
+ "Do you want to generate a config.ini file?", ("No", "Yes")
381
+ )
382
+
383
+
384
+ if generate_config_radio == "Yes":
385
+ # Create a config parser object
386
+ config = configparser.ConfigParser()
387
+
388
+ # Main section
389
+ config["FileSettings"] = {}
390
+ config["DownloadOptions"] = {}
391
+ config["FixTime"] = {"is_time_modified": "False"}
392
+ config["SensorTest"] = {"sensor_test": "False"}
393
+ config["QCTest"] = {"qc_test": "False"}
394
+ config["ProfileTest"] = {"profile_test": "False"}
395
+ config["VelocityTest"] = {"velocity_test": "False"}
396
+ config["Attributes"] = {}
397
+
398
+ # ------------------
399
+ # File Settings
400
+ # ------------------
401
+ config["FileSettings"]["input_file_path"] = ""
402
+ config["FileSettings"]["input_file_name"] = st.session_state.fname
403
+ config["FileSettings"]["output_file_path"] = ""
404
+ config["FileSettings"]["output_file_name_raw_netcdf"] = ""
405
+ config["FileSettings"]["output_file_name_flead_netcdf"] = ""
406
+ config["FileSettings"]["output_file_name_vlead_netcdf"] = ""
407
+ config["FileSettings"]["output_file_name_raw_csv"] = ""
408
+ config["FileSettings"]["output_file_name_processed_netcdf"] = ""
409
+ config["FileSettings"]["output_file_name_processed_csv"] = ""
410
+
411
+ if st.session_state.file_type_WF.lower() == "netcdf":
412
+ st.session_state.isProcessedNetcdfDownload_WF = True
413
+ else:
414
+ st.session_state.isProcessedNetcdfDownload_WF = False
415
+ st.session_state.isProcessedCSVDownload_WF = True
416
+ # ------------------
417
+ # Download options
418
+ # ------------------
419
+ config["DownloadOptions"]["download_raw_netcdf"] = str(
420
+ st.session_state.rawnc_download_DRW
421
+ )
422
+ config["DownloadOptions"]["download_flead_netcdf"] = str(
423
+ st.session_state.fleadnc_download_DRW
424
+ )
425
+ config["DownloadOptions"]["download_vlead_netcdf"] = str(
426
+ st.session_state.vleadnc_download_DRW
427
+ )
428
+ config["DownloadOptions"]["download_processed_netcdf"] = str(
429
+ st.session_state.isProcessedNetcdfDownload_WF
430
+ )
431
+ config["DownloadOptions"]["download_raw_csv"] = str(
432
+ st.session_state.rawcsv_download_DRW
433
+ )
434
+ config["DownloadOptions"]["download_processed_csv"] = str(
435
+ st.session_state.isProcessedCSVDownload_WF
436
+ )
437
+ config["DownloadOptions"]["add_attributes_raw"] = str(
438
+ st.session_state.add_attributes_DRW
439
+ )
440
+ config["DownloadOptions"]["add_attributes_processed"] = str(
441
+ st.session_state.isAttributes
442
+ )
443
+ config["DownloadOptions"]["axis_option"] = str(st.session_state.axis_option_DRW)
444
+ config["DownloadOptions"]["apply_mask"] = "True"
445
+ config["DownloadOptions"]["download_mask"] = "True"
446
+
447
+ # -----------------
448
+ # PAGE: Read File (Fix Time)
449
+ # -----------------
450
+
451
+ config["FixTime"]["is_time_modified"] = str(st.session_state.isTimeAxisModified)
452
+ config["FixTime"]["is_snap_time_axis"] = str(st.session_state.isSnapTimeAxis)
453
+ config["FixTime"]["time_snap_frequency"] = str(st.session_state.time_snap_frequency)
454
+ config["FixTime"]["time_snap_tolerance"] = str(st.session_state.time_snap_tolerance)
455
+ config["FixTime"]["time_target_minute"] = str(st.session_state.time_target_minute)
456
+ config["FixTime"]["is_time_gap_filled"] = str(st.session_state.isTimeGapFilled)
457
+
458
+ # ------------------
459
+ # PAGE: Sensor Test
460
+ # ------------------
461
+ config["SensorTest"]["sensor_test"] = str(st.session_state.isSensorTest)
462
+ # Tab 1: Depth Sensor
463
+ config["SensorTest"]["is_depth_modified"] = str(st.session_state.isDepthModified_ST)
464
+ config["SensorTest"]["depth_input_option"] = str(st.session_state.depthoption_ST)
465
+ config["SensorTest"]["is_fixed_depth"] = str(st.session_state.isFixedDepth_ST)
466
+ config["SensorTest"]["fixed_depth"] = str(st.session_state.fixeddepth_ST)
467
+ config["SensorTest"]["is_upload_depth"] = str(st.session_state.isUploadDepth_ST)
468
+ config["SensorTest"]["depth_file_path"] = ""
469
+
470
+ # Tab 2: Salinity sensor
471
+ config["SensorTest"]["is_salinity_modified"] = str(
472
+ st.session_state.isSalinityModified_ST
473
+ )
474
+ config["SensorTest"]["salinity_input_option"] = str(
475
+ st.session_state.salinityoption_ST
476
+ )
477
+ config["SensorTest"]["is_fixed_salinity"] = str(st.session_state.isFixedSalinity_ST)
478
+ config["SensorTest"]["fixed_salinity"] = str(st.session_state.fixedsalinity_ST)
479
+ config["SensorTest"]["is_upload_salinity"] = str(
480
+ st.session_state.isUploadSalinity_ST
481
+ )
482
+ config["SensorTest"]["salinity_file_path"] = ""
483
+
484
+ # Tab 3: Temperature sensor
485
+ config["SensorTest"]["is_temperature_modified"] = str(
486
+ st.session_state.isTemperatureModified_ST
487
+ )
488
+ config["SensorTest"]["temperature_input_option"] = str(
489
+ st.session_state.temperatureoption_ST
490
+ )
491
+ config["SensorTest"]["is_fixed_temperature"] = str(
492
+ st.session_state.isFixedTemperature_ST
493
+ )
494
+ config["SensorTest"]["fixed_temperature"] = str(
495
+ st.session_state.fixedtemperature_ST
496
+ )
497
+ config["SensorTest"]["is_upload_temperature"] = str(
498
+ st.session_state.isUploadTemperature_ST
499
+ )
500
+ config["SensorTest"]["temperature_file_path"] = ""
501
+
502
+ # Tab 7:
503
+
504
+ config["SensorTest"]["roll_check"] = str(st.session_state.isRollCheck_ST)
505
+ config["SensorTest"]["roll_cutoff"] = str(st.session_state.roll_cutoff_ST)
506
+ config["SensorTest"]["pitch_check"] = str(st.session_state.isPitchCheck_ST)
507
+ config["SensorTest"]["pitch_cutoff"] = str(st.session_state.pitch_cutoff_ST)
508
+
509
+ config["SensorTest"]["velocity_modified"] = str(
510
+ st.session_state.isVelocityModifiedSound_ST
511
+ )
512
+
513
+ # ------------------
514
+ # PAGE: QC Test
515
+ # ------------------
516
+ # Tab 2
517
+ config["QCTest"]["qc_test"] = str(st.session_state.isQCTest)
518
+ config["QCTest"]["qc_check"] = str(st.session_state.isQCCheck_QCT)
519
+ config["QCTest"]["correlation"] = str(st.session_state.ct_QCT)
520
+ config["QCTest"]["echo_intensity"] = str(st.session_state.et_QCT)
521
+ config["QCTest"]["error_velocity"] = str(st.session_state.evt_QCT)
522
+ config["QCTest"]["false_target"] = str(st.session_state.ft_QCT)
523
+ config["QCTest"]["three_beam"] = str(st.session_state.is3beam_QCT)
524
+ if st.session_state.is3beam_QCT:
525
+ config["QCTest"]["beam_ignore"] = str(st.session_state.beam_to_ignore)
526
+ config["QCTest"]["percent_good"] = str(st.session_state.pgt_QCT)
527
+
528
+ # Tab 4
529
+ config["QCTest"]["beam_modified"] = str(st.session_state.isBeamModified_QCT)
530
+ config["QCTest"]["orientation"] = str(st.session_state.beam_direction_QCT)
531
+
532
+ # ------------------
533
+ # PAGE: Profile Test
534
+ # ------------------
535
+ # Tab 1
536
+ config["ProfileTest"]["profile_test"] = str(st.session_state.isProfileTest)
537
+ config["ProfileTest"]["trim_ends_check"] = str(st.session_state.isTrimEndsCheck_PT)
538
+ config["ProfileTest"]["trim_start_ensemble"] = str(st.session_state.start_ens_PT)
539
+ config["ProfileTest"]["trim_end_ensemble"] = str(st.session_state.end_ens_PT)
540
+
541
+ # Tab 2
542
+ config["ProfileTest"]["cutbins_sidelobe_check"] = str(
543
+ st.session_state.isCutBinSideLobeCheck_PT
544
+ )
545
+ config["ProfileTest"]["extra_cells"] = str(st.session_state.extra_cells_PT)
546
+ config["ProfileTest"]["water_depth"] = str(st.session_state.water_depth_PT)
547
+
548
+ # Tab 3
549
+ # config["ProfileTest"]["manual_cutbins"] = str(
550
+ # st.session_state.isCutBinManualCheck_PT
551
+ # )
552
+
553
+ # Tab 4
554
+ config["ProfileTest"]["regrid"] = str(st.session_state.isRegridCheck_PT)
555
+ config["ProfileTest"]["end_cell_option"] = str(st.session_state.end_cell_option_PT)
556
+ config["ProfileTest"]["interpolate"] = str(st.session_state.interpolate_PT)
557
+ config["ProfileTest"]["boundary"] = str(st.session_state.manualdepth_PT)
558
+
559
+ # ------------------
560
+ # PAGE: Velocity Test
561
+ # ------------------
562
+
563
+ config["VelocityTest"]["velocity_test"] = str(st.session_state.isVelocityTest)
564
+
565
+ # Tab 1
566
+ config["VelocityTest"]["magnetic_declination"] = str(
567
+ st.session_state.isMagnetCheck_VT
568
+ )
569
+ config["VelocityTest"]["magnet_method"] = str(st.session_state.magnet_method_VT)
570
+ config["VelocityTest"]["magnet_latitude"] = str(st.session_state.magnet_lat_VT)
571
+ config["VelocityTest"]["magnet_longitude"] = str(st.session_state.magnet_lon_VT)
572
+ config["VelocityTest"]["magnet_depth"] = str(st.session_state.magnet_depth_VT)
573
+ config["VelocityTest"]["magnet_year"] = str(st.session_state.magnet_year_VT)
574
+ config["VelocityTest"]["magnet_user_input"] = str(
575
+ st.session_state.magnet_user_input_VT
576
+ )
577
+
578
+ # Tab 2
579
+ config["VelocityTest"]["cutoff"] = str(st.session_state.isCutoffCheck_VT)
580
+ config["VelocityTest"]["max_zonal_velocity"] = str(st.session_state.maxuvel_VT)
581
+ config["VelocityTest"]["max_meridional_velocity"] = str(st.session_state.maxvvel_VT)
582
+ config["VelocityTest"]["max_vertical_velocity"] = str(st.session_state.maxwvel_VT)
583
+
584
+ # Tab 3
585
+ config["VelocityTest"]["despike"] = str(st.session_state.isDespikeCheck_VT)
586
+ config["VelocityTest"]["despike_kernel_size"] = str(
587
+ st.session_state.despike_kernel_VT
588
+ )
589
+ config["VelocityTest"]["despike_cutoff"] = str(st.session_state.despike_cutoff_VT)
590
+
591
+ # Tab 4
592
+ config["VelocityTest"]["flatline"] = str(st.session_state.isFlatlineCheck_VT)
593
+ config["VelocityTest"]["flatline_kernel_size"] = str(
594
+ st.session_state.flatline_kernel_VT
595
+ )
596
+ config["VelocityTest"]["flatline_cutoff"] = str(st.session_state.flatline_cutoff_VT)
597
+
598
+ # Optional section (attributes)
599
+
600
+ for key, value in st.session_state.attributes.items():
601
+ config["Attributes"][key] = str(value) # Ensure all values are strings
602
+
603
+ # Write config.ini to a temporary file
604
+ # config_filepath = "config.ini"
605
+ # with open(config_filepath, "w") as configfile:
606
+ # config.write(configfile)
607
+ # Create a temporary file for the config.ini
608
+ with tempfile.NamedTemporaryFile("w+", delete=False, suffix=".ini") as temp_config:
609
+ config.write(temp_config)
610
+ temp_config_path = temp_config.name
611
+ # Allow the user to download the generated config.ini file
612
+ with open(temp_config_path, "rb") as file:
613
+ st.download_button(
614
+ label="Download config.ini File",
615
+ data=file,
616
+ file_name="config.ini",
617
+ )
618
+
619
+ display_config_radio = st.radio(
620
+ "Do you want to display config.ini file?", ("No", "Yes")
621
+ )
622
+ if display_config_radio == "Yes":
623
+ st.write({section: dict(config[section]) for section in config.sections()})