pyadps 0.2.0b0__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 -211
- 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.0b0.dist-info → pyadps-0.3.0.dist-info}/METADATA +63 -33
- pyadps-0.3.0.dist-info/RECORD +35 -0
- {pyadps-0.2.0b0.dist-info → pyadps-0.3.0.dist-info}/WHEEL +1 -1
- {pyadps-0.2.0b0.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.0b0.dist-info/RECORD +0 -31
- {pyadps-0.2.0b0.dist-info → pyadps-0.3.0.dist-info}/LICENSE +0 -0
pyadps/utils/velocity_test.py
CHANGED
@@ -1,9 +1,24 @@
|
|
1
1
|
from itertools import groupby
|
2
|
+
from pygeomag import GeoMag
|
2
3
|
|
3
4
|
import requests
|
4
5
|
import numpy as np
|
5
6
|
import scipy as sp
|
6
7
|
|
8
|
+
|
9
|
+
def magdec(glat, glon, alt, time):
|
10
|
+
# Selecting COF file According to given year
|
11
|
+
if time >= 2010 and time < 2030:
|
12
|
+
var = 2010 + (int(time) - 2010) // 5 * 5
|
13
|
+
file_name = "wmm/WMM_{}.COF".format(str(var))
|
14
|
+
geo_mag = GeoMag(coefficients_file=file_name)
|
15
|
+
else:
|
16
|
+
geo_mag = GeoMag("wmm/WMM_2025.COF")
|
17
|
+
result = geo_mag.calculate(glat=glat, glon=glon, alt=alt, time=time)
|
18
|
+
|
19
|
+
return [[result.d]]
|
20
|
+
|
21
|
+
|
7
22
|
def wmm2020api(lat1, lon1, year):
|
8
23
|
"""
|
9
24
|
This function uses the WMM2020 API to retrieve the magnetic field values at a given location
|
@@ -18,37 +33,60 @@ def wmm2020api(lat1, lon1, year):
|
|
18
33
|
Returns:
|
19
34
|
mag -> magnetic declination at the given location in degree.
|
20
35
|
"""
|
21
|
-
|
36
|
+
baseurl_wmm = (
|
37
|
+
"https://www.ngdc.noaa.gov/geomag-web/calculators/calculateDeclination?"
|
38
|
+
)
|
39
|
+
baseurl_igrf = (
|
40
|
+
"https://www.ngdc.noaa.gov/geomag-web/calculators/calculateDeclination?"
|
41
|
+
)
|
42
|
+
baseurl_emm = "https://emmcalc.geomag.info/?magneticcomponent=d&"
|
22
43
|
key = "zNEw7"
|
23
|
-
resultFormat="json"
|
24
|
-
|
44
|
+
resultFormat = "json"
|
45
|
+
if year >= 2025:
|
46
|
+
baseurl = baseurl_wmm
|
47
|
+
model = "WMM"
|
48
|
+
elif year >= 2019:
|
49
|
+
baseurl = baseurl_wmm
|
50
|
+
model = "IGRF"
|
51
|
+
elif year >= 2000:
|
52
|
+
baseurl = baseurl_emm
|
53
|
+
model = "EMM"
|
54
|
+
elif year >= 1590:
|
55
|
+
baseurl = baseurl_igrf
|
56
|
+
model = "IGRF"
|
57
|
+
url = "{}model={}&lat1={}&lon1={}&key={}&startYear={}&resultFormat={}".format(
|
58
|
+
baseurl, model, lat1, lon1, key, year, resultFormat
|
59
|
+
)
|
25
60
|
response = requests.get(url)
|
26
61
|
data = response.json()
|
27
62
|
results = data["result"][0]
|
28
63
|
mag = [[results["declination"]]]
|
29
|
-
|
64
|
+
|
30
65
|
return mag
|
31
66
|
|
32
|
-
def magnetic_declination(lat, lon, depth, year):
|
33
|
-
"""
|
34
|
-
The function calculates the magnetic declination at a given location and depth.
|
35
|
-
using a local installation of wmm2020 model.
|
36
67
|
|
68
|
+
# Commentin magnetic_declination model since the method is no longer using.
|
69
|
+
# def magnetic_declination(lat, lon, depth, year):
|
70
|
+
# """
|
71
|
+
# The function calculates the magnetic declination at a given location and depth.
|
72
|
+
# using a local installation of wmm2020 model.
|
37
73
|
|
38
|
-
Args:
|
39
|
-
lat (parameter, float): Latitude in decimals
|
40
|
-
lon (parameter, float): Longitude in decimals
|
41
|
-
depth (parameter, float): depth in m
|
42
|
-
year (parameter, integer): Year
|
43
74
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
75
|
+
# Args:
|
76
|
+
# lat (parameter, float): Latitude in decimals
|
77
|
+
# lon (parameter, float): Longitude in decimals
|
78
|
+
# depth (parameter, float): depth in m
|
79
|
+
# year (parameter, integer): Year
|
80
|
+
|
81
|
+
# Returns:
|
82
|
+
# mag: Magnetic declination (degrees)
|
83
|
+
# """
|
84
|
+
# import wmm2020
|
85
|
+
# mag = wmm2020.wmm(lat, lon, depth, year)
|
86
|
+
# mag = mag.decl.data
|
87
|
+
|
88
|
+
# return mag
|
50
89
|
|
51
|
-
return mag
|
52
90
|
|
53
91
|
def velocity_modifier(velocity, mag):
|
54
92
|
"""
|
@@ -64,12 +102,17 @@ def velocity_modifier(velocity, mag):
|
|
64
102
|
"""
|
65
103
|
mag = np.deg2rad(mag[0][0])
|
66
104
|
velocity = np.where(velocity == -32768, np.nan, velocity)
|
67
|
-
velocity[0, :, :] = velocity[0, :, :] * np.cos(mag) + velocity[1, :, :] * np.sin(
|
68
|
-
|
105
|
+
velocity[0, :, :] = velocity[0, :, :] * np.cos(mag) + velocity[1, :, :] * np.sin(
|
106
|
+
mag
|
107
|
+
)
|
108
|
+
velocity[1, :, :] = -1 * velocity[0, :, :] * np.sin(mag) + velocity[
|
109
|
+
1, :, :
|
110
|
+
] * np.cos(mag)
|
69
111
|
velocity = np.where(velocity == np.nan, -32768, velocity)
|
70
112
|
|
71
113
|
return velocity
|
72
114
|
|
115
|
+
|
73
116
|
def velocity_cutoff(velocity, mask, cutoff=250):
|
74
117
|
"""
|
75
118
|
Masks all velocities above a cutoff. Note that
|
@@ -89,7 +132,7 @@ def velocity_cutoff(velocity, mask, cutoff=250):
|
|
89
132
|
return mask
|
90
133
|
|
91
134
|
|
92
|
-
def despike(velocity, mask,
|
135
|
+
def despike(velocity, mask, kernel_size=13, cutoff=3):
|
93
136
|
"""
|
94
137
|
Function to remove anomalous spikes in the data over a period of time.
|
95
138
|
A median filter is used to despike the data.
|
@@ -97,26 +140,31 @@ def despike(velocity, mask, kernal_size=13, cutoff=150):
|
|
97
140
|
Args:
|
98
141
|
velocity (numpy array, integer): Velocity(depth, time) in mm/s
|
99
142
|
mask (numpy array, integer): Mask file
|
100
|
-
|
101
|
-
cutoff (parameter, integer):
|
143
|
+
kernel_size (paramater, integer): Window size for rolling median filter
|
144
|
+
cutoff (parameter, integer): Number of standard deviations to identify spikes
|
102
145
|
|
103
146
|
Returns:
|
104
147
|
mask
|
105
148
|
"""
|
106
|
-
cutoff = cutoff * 10
|
107
149
|
velocity = np.where(velocity == -32768, np.nan, velocity)
|
108
150
|
shape = np.shape(velocity)
|
109
151
|
for j in range(shape[0]):
|
110
|
-
|
152
|
+
# Apply median filter
|
153
|
+
filt = sp.signal.medfilt(velocity[j, :], kernel_size)
|
154
|
+
# Calculate absolute deviation from the rolling median
|
111
155
|
diff = np.abs(velocity[j, :] - filt)
|
112
|
-
|
156
|
+
# Calculate threshold for spikes based on standard deviation
|
157
|
+
std_dev = np.nanstd(diff)
|
158
|
+
spike_threshold = cutoff * std_dev
|
159
|
+
# Apply mask after identifying spikes
|
160
|
+
mask[j, :] = np.where(diff < spike_threshold, mask[j, :], 1)
|
113
161
|
return mask
|
114
162
|
|
115
163
|
|
116
164
|
def flatline(
|
117
165
|
velocity,
|
118
166
|
mask,
|
119
|
-
|
167
|
+
kernel_size=4,
|
120
168
|
cutoff=1,
|
121
169
|
):
|
122
170
|
"""
|
@@ -126,7 +174,7 @@ def flatline(
|
|
126
174
|
Args:
|
127
175
|
velocity (numpy arrray, integer): Velocity (depth, time)
|
128
176
|
mask (numpy array, integer): Mask file
|
129
|
-
|
177
|
+
kernel_size (parameter, integer): No. of ensembles over which flatline has to be detected
|
130
178
|
cutoff (parameter, integer): Permitted deviation in velocity
|
131
179
|
|
132
180
|
Returns:
|
@@ -143,7 +191,7 @@ def flatline(
|
|
143
191
|
for k, g in groupby(dummymask):
|
144
192
|
# subset_size = sum(1 for i in g)
|
145
193
|
subset_size = len(list(g))
|
146
|
-
if k == 1 and subset_size >=
|
194
|
+
if k == 1 and subset_size >= kernel_size:
|
147
195
|
mask[j, index : index + subset_size] = 1
|
148
196
|
index = index + subset_size
|
149
197
|
dummymask = np.zeros(shape[1])
|
pyadps/utils/writenc.py
CHANGED
@@ -17,7 +17,6 @@ from netCDF4 import date2num
|
|
17
17
|
from pyadps.utils import readrdi as rd
|
18
18
|
|
19
19
|
|
20
|
-
|
21
20
|
def pd2nctime(time, t0="hours since 2000-01-01"):
|
22
21
|
"""
|
23
22
|
Function to convert pandas datetime format to netcdf datetime format.
|
@@ -68,7 +67,14 @@ def flead_ncatt(fl_obj, ncfile_id, ens=0):
|
|
68
67
|
setattr(ncfile_id, format_key, format(value))
|
69
68
|
|
70
69
|
|
71
|
-
def rawnc(
|
70
|
+
def rawnc(
|
71
|
+
infile,
|
72
|
+
outfile,
|
73
|
+
axis_option="time",
|
74
|
+
fixensemble=True,
|
75
|
+
attributes=None,
|
76
|
+
t0="hours since 2000-01-01",
|
77
|
+
):
|
72
78
|
"""
|
73
79
|
rawnc is a function to create netcdf file. Stores 3-D data types like
|
74
80
|
velocity, echo, correlation, and percent good.
|
@@ -85,7 +91,12 @@ def rawnc(infile, outfile, time, axis_option=None, attributes=None, t0="hours si
|
|
85
91
|
|
86
92
|
outnc = nc4.Dataset(outfile, "w", format="NETCDF4")
|
87
93
|
|
88
|
-
|
94
|
+
ds = rd.ReadFile(infile)
|
95
|
+
if fixensemble and not ds.isFixedEnsemble:
|
96
|
+
ds.fixensemble()
|
97
|
+
|
98
|
+
head = ds.fileheader
|
99
|
+
flead = ds.fixedleader
|
89
100
|
cell_list = flead.fleader["Cells"]
|
90
101
|
beam_list = flead.fleader["Beams"]
|
91
102
|
|
@@ -96,8 +107,11 @@ def rawnc(infile, outfile, time, axis_option=None, attributes=None, t0="hours si
|
|
96
107
|
primary_axis = "ensemble"
|
97
108
|
ensemble = outnc.createVariable("ensemble", "i4", ("ensemble",))
|
98
109
|
ensemble.axis = "T"
|
110
|
+
# Add ensemble
|
111
|
+
total_ensembles = ds.ensembles
|
112
|
+
ensemble = np.arange(1, total_ensembles + 1, 1)
|
99
113
|
elif axis_option == "time":
|
100
|
-
tsize =
|
114
|
+
tsize = ds.ensembles
|
101
115
|
outnc.createDimension("time", tsize)
|
102
116
|
primary_axis = "time"
|
103
117
|
time_var = outnc.createVariable("time", "i4", ("time",))
|
@@ -106,6 +120,7 @@ def rawnc(infile, outfile, time, axis_option=None, attributes=None, t0="hours si
|
|
106
120
|
time_var.long_name = "time"
|
107
121
|
|
108
122
|
# Convert time_data to numerical format
|
123
|
+
time = ds.time
|
109
124
|
nctime = pd2nctime(time, t0)
|
110
125
|
time_var[:] = nctime
|
111
126
|
|
@@ -128,7 +143,7 @@ def rawnc(infile, outfile, time, axis_option=None, attributes=None, t0="hours si
|
|
128
143
|
cell[:] = np.arange(1, max(cell_list) + 1, 1)
|
129
144
|
beam[:] = np.arange(1, max(beam_list) + 1, 1)
|
130
145
|
|
131
|
-
varlist =
|
146
|
+
varlist = head.data_types(1)
|
132
147
|
varlist.remove("Fixed Leader")
|
133
148
|
varlist.remove("Variable Leader")
|
134
149
|
|
@@ -139,10 +154,8 @@ def rawnc(infile, outfile, time, axis_option=None, attributes=None, t0="hours si
|
|
139
154
|
varid[i] = outnc.createVariable(
|
140
155
|
item, "i2", (primary_axis, "cell", "beam"), fill_value=-32768
|
141
156
|
)
|
142
|
-
|
143
|
-
|
144
|
-
var = vel(infile).data
|
145
|
-
# var = rd.variables(infile, item)
|
157
|
+
vel = getattr(ds, item.lower())
|
158
|
+
var = vel.data
|
146
159
|
|
147
160
|
else:
|
148
161
|
# Unsigned integers might be assigned for future netcdf versions
|
@@ -150,34 +163,34 @@ def rawnc(infile, outfile, time, axis_option=None, attributes=None, t0="hours si
|
|
150
163
|
varid[i] = outnc.createVariable(
|
151
164
|
format_item, "i2", (primary_axis, "cell", "beam")
|
152
165
|
)
|
153
|
-
datatype = getattr(
|
154
|
-
var = np.array(datatype
|
155
|
-
# var = np.array(rd.variables(infile, item), dtype="int16")
|
166
|
+
datatype = getattr(ds, format_item.lower())
|
167
|
+
var = np.array(datatype.data, dtype="int16")
|
156
168
|
|
157
169
|
vshape = var.T.shape
|
158
|
-
if i == 0:
|
159
|
-
if primary_axis == "time":
|
160
|
-
time[:] = np.arange(1, vshape[0] + 1, 1)
|
161
|
-
elif primary_axis == "ensemble":
|
162
|
-
ensemble[:] = np.arange(1, vshape[0] + 1, 1)
|
163
|
-
else:
|
164
|
-
raise ValueError(f"Invalid axis_option: {axis_option}.")
|
165
170
|
|
166
171
|
varid[i][0 : vshape[0], 0 : vshape[1], 0 : vshape[2]] = var.T
|
167
|
-
|
172
|
+
|
168
173
|
# Add global attributes if provided
|
169
174
|
if attributes:
|
170
175
|
for key, value in attributes.items():
|
171
|
-
setattr(
|
176
|
+
setattr(
|
177
|
+
outnc, key, str(value)
|
178
|
+
) # Convert to string to store in NetCDF metadata
|
172
179
|
|
173
180
|
# outnc.history = "Created " + time.ctime(time.time())
|
174
181
|
flead_ncatt(flead, outnc)
|
175
|
-
|
176
182
|
|
177
183
|
outnc.close()
|
178
184
|
|
179
185
|
|
180
|
-
def
|
186
|
+
def flead_nc(
|
187
|
+
infile,
|
188
|
+
outfile,
|
189
|
+
axis_option="time",
|
190
|
+
fixensemble=True,
|
191
|
+
attributes=None,
|
192
|
+
t0="hours since 2000-01-01",
|
193
|
+
):
|
181
194
|
"""
|
182
195
|
Function to create ncfile containing Variable Leader.
|
183
196
|
|
@@ -187,6 +200,11 @@ def vlead_nc(infile, outfile, time, axis_option=None, attributes=None, t0="hours
|
|
187
200
|
"""
|
188
201
|
outnc = nc4.Dataset(outfile, "w", format="NETCDF4")
|
189
202
|
|
203
|
+
# Read Binary File
|
204
|
+
ds = rd.ReadFile(infile)
|
205
|
+
if fixensemble:
|
206
|
+
ds.fixensemble()
|
207
|
+
flead = ds.fixedleader
|
190
208
|
# Dimensions
|
191
209
|
# Define the primary axis based on axis_option
|
192
210
|
if axis_option == "ensemble":
|
@@ -194,8 +212,12 @@ def vlead_nc(infile, outfile, time, axis_option=None, attributes=None, t0="hours
|
|
194
212
|
primary_axis = "ensemble"
|
195
213
|
ensemble = outnc.createVariable("ensemble", "i4", ("ensemble",))
|
196
214
|
ensemble.axis = "T"
|
215
|
+
# Add ensemble
|
216
|
+
total_ensembles = ds.ensembles
|
217
|
+
ensemble = np.arange(1, total_ensembles + 1, 1)
|
218
|
+
|
197
219
|
elif axis_option == "time":
|
198
|
-
tsize =
|
220
|
+
tsize = ds.ensembles
|
199
221
|
outnc.createDimension("time", tsize)
|
200
222
|
primary_axis = "time"
|
201
223
|
time_var = outnc.createVariable("time", "i4", ("time",))
|
@@ -204,6 +226,7 @@ def vlead_nc(infile, outfile, time, axis_option=None, attributes=None, t0="hours
|
|
204
226
|
time_var.long_name = "time"
|
205
227
|
|
206
228
|
# Convert time_data to numerical format
|
229
|
+
time = ds.time
|
207
230
|
nctime = pd2nctime(time, t0)
|
208
231
|
time_var[:] = nctime
|
209
232
|
|
@@ -211,8 +234,81 @@ def vlead_nc(infile, outfile, time, axis_option=None, attributes=None, t0="hours
|
|
211
234
|
raise ValueError(f"Invalid axis_option: {axis_option}.")
|
212
235
|
|
213
236
|
# Variables
|
237
|
+
fdict = flead.fleader
|
238
|
+
varid = [0] * len(fdict)
|
239
|
+
|
240
|
+
i = 0
|
241
|
+
|
242
|
+
for key, values in fdict.items():
|
243
|
+
format_item = key.replace(" ", "_")
|
244
|
+
varid[i] = outnc.createVariable(
|
245
|
+
format_item, "i4", primary_axis, fill_value=-32768
|
246
|
+
)
|
247
|
+
var = values
|
248
|
+
vshape = var.shape
|
249
|
+
|
250
|
+
varid[i][0 : vshape[0]] = var
|
251
|
+
i += 1
|
214
252
|
|
215
|
-
|
253
|
+
# Add global attributes if provided
|
254
|
+
if attributes:
|
255
|
+
for key, value in attributes.items():
|
256
|
+
setattr(outnc, key, str(value)) # Store attributes as strings
|
257
|
+
|
258
|
+
outnc.close()
|
259
|
+
|
260
|
+
|
261
|
+
def vlead_nc(
|
262
|
+
infile,
|
263
|
+
outfile,
|
264
|
+
axis_option="time",
|
265
|
+
fixensemble=True,
|
266
|
+
attributes=None,
|
267
|
+
t0="hours since 2000-01-01",
|
268
|
+
):
|
269
|
+
"""
|
270
|
+
Function to create ncfile containing Variable Leader.
|
271
|
+
|
272
|
+
Args:
|
273
|
+
infile (string): Input file path including filename
|
274
|
+
outfile (string): Output file path including filename
|
275
|
+
"""
|
276
|
+
# Create output NetCDF File
|
277
|
+
outnc = nc4.Dataset(outfile, "w", format="NETCDF4")
|
278
|
+
|
279
|
+
# Read Binary File
|
280
|
+
ds = rd.ReadFile(infile)
|
281
|
+
if fixensemble:
|
282
|
+
ds.fixensemble()
|
283
|
+
vlead = ds.variableleader
|
284
|
+
# Dimensions
|
285
|
+
# Define the primary axis based on axis_option
|
286
|
+
if axis_option == "ensemble":
|
287
|
+
outnc.createDimension("ensemble", None)
|
288
|
+
primary_axis = "ensemble"
|
289
|
+
ensemble = outnc.createVariable("ensemble", "i4", ("ensemble",))
|
290
|
+
ensemble.axis = "T"
|
291
|
+
# Add ensemble
|
292
|
+
total_ensembles = ds.ensembles
|
293
|
+
ensemble = np.arange(1, total_ensembles + 1, 1)
|
294
|
+
elif axis_option == "time":
|
295
|
+
tsize = ds.ensembles
|
296
|
+
outnc.createDimension("time", tsize)
|
297
|
+
primary_axis = "time"
|
298
|
+
time_var = outnc.createVariable("time", "i4", ("time",))
|
299
|
+
time_var.axis = "T"
|
300
|
+
time_var.units = t0
|
301
|
+
time_var.long_name = "time"
|
302
|
+
|
303
|
+
# Convert time_data to numerical format
|
304
|
+
time = ds.time
|
305
|
+
nctime = pd2nctime(time, t0)
|
306
|
+
time_var[:] = nctime
|
307
|
+
|
308
|
+
else:
|
309
|
+
raise ValueError(f"Invalid axis_option: {axis_option}.")
|
310
|
+
|
311
|
+
# Read Data
|
216
312
|
vdict = vlead.vleader
|
217
313
|
varid = [0] * len(vdict)
|
218
314
|
|
@@ -224,18 +320,12 @@ def vlead_nc(infile, outfile, time, axis_option=None, attributes=None, t0="hours
|
|
224
320
|
format_item, "i4", primary_axis, fill_value=-32768
|
225
321
|
)
|
226
322
|
var = values
|
227
|
-
vshape = var.shape
|
228
|
-
if i == 0:
|
229
|
-
if primary_axis == "time":
|
230
|
-
time[:] = np.arange(1, vshape[0] + 1, 1)
|
231
|
-
elif primary_axis == "ensemble":
|
232
|
-
ensemble[:] = np.arange(1, vshape[0] + 1, 1)
|
233
|
-
else:
|
234
|
-
raise ValueError(f"Invalid axis_option: {axis_option}.")
|
323
|
+
# vshape = var.shape
|
235
324
|
|
236
|
-
varid[i][0 :
|
325
|
+
varid[i][0 : ds.ensembles] = var
|
326
|
+
# varid[i][0 : vshape[0]] = var
|
237
327
|
i += 1
|
238
|
-
|
328
|
+
|
239
329
|
# Add global attributes if provided
|
240
330
|
if attributes:
|
241
331
|
for key, value in attributes.items():
|
@@ -244,7 +334,18 @@ def vlead_nc(infile, outfile, time, axis_option=None, attributes=None, t0="hours
|
|
244
334
|
outnc.close()
|
245
335
|
|
246
336
|
|
247
|
-
def finalnc(
|
337
|
+
def finalnc(
|
338
|
+
outfile,
|
339
|
+
depth,
|
340
|
+
final_mask,
|
341
|
+
final_echo,
|
342
|
+
final_corr,
|
343
|
+
final_pgood,
|
344
|
+
time,
|
345
|
+
data,
|
346
|
+
t0="hours since 2000-01-01",
|
347
|
+
attributes=None,
|
348
|
+
):
|
248
349
|
"""
|
249
350
|
Function to create the processed NetCDF file.
|
250
351
|
|
@@ -259,15 +360,19 @@ def finalnc(outfile, depth, time, data, t0="hours since 2000-01-01", attributes=
|
|
259
360
|
|
260
361
|
# Change velocity to cm/s
|
261
362
|
data = data.astype(np.float64)
|
262
|
-
data[data > fill] /= 10
|
363
|
+
data[data > fill] /= 10
|
263
364
|
|
264
365
|
# Change depth to positive
|
265
|
-
depth = abs(depth)
|
366
|
+
# depth = abs(depth)
|
266
367
|
|
267
368
|
# Reverse the arrays if depth in descending order
|
268
369
|
if np.all(depth[:-1] >= depth[1:]):
|
269
370
|
depth = depth[::-1]
|
270
371
|
data = data[:, ::-1, :]
|
372
|
+
final_mask = final_mask[::-1, :]
|
373
|
+
final_echo = final_echo[:, ::-1, :]
|
374
|
+
final_corr = final_corr[:, ::-1, :]
|
375
|
+
final_pgood = final_pgood[:, ::-1, :]
|
271
376
|
|
272
377
|
ncfile = nc4.Dataset(outfile, mode="w", format="NETCDF4")
|
273
378
|
# Check if depth is scalar or array
|
@@ -307,6 +412,69 @@ def finalnc(outfile, depth, time, data, t0="hours since 2000-01-01", attributes=
|
|
307
412
|
evel.units = "cm/s"
|
308
413
|
evel.long_name = "error_velocity"
|
309
414
|
|
415
|
+
mvel = ncfile.createVariable("mask", np.float32, ("time", "depth"), fill_value=fill)
|
416
|
+
mvel.long_name = "Velocity Mask (1: bad value, 0: good value)"
|
417
|
+
|
418
|
+
echo1 = ncfile.createVariable(
|
419
|
+
"echo1", np.float32, ("time", "depth"), fill_value=-32768
|
420
|
+
)
|
421
|
+
echo1.long_name = "Echo intensity Beam 1"
|
422
|
+
|
423
|
+
echo2 = ncfile.createVariable(
|
424
|
+
"echo2", np.float32, ("time", "depth"), fill_value=-32768
|
425
|
+
)
|
426
|
+
echo2.long_name = "Echo intensity Beam 2"
|
427
|
+
|
428
|
+
echo3 = ncfile.createVariable(
|
429
|
+
"echo3", np.float32, ("time", "depth"), fill_value=-32768
|
430
|
+
)
|
431
|
+
echo3.long_name = "Echo intensity Beam 3"
|
432
|
+
|
433
|
+
echo4 = ncfile.createVariable(
|
434
|
+
"echo4", np.float32, ("time", "depth"), fill_value=-32768
|
435
|
+
)
|
436
|
+
echo4.long_name = "Echo intensity Beam 4"
|
437
|
+
|
438
|
+
corr1 = ncfile.createVariable(
|
439
|
+
"corr1", np.float32, ("time", "depth"), fill_value=-32768
|
440
|
+
)
|
441
|
+
corr1.long_name = "Beam 1 correlation"
|
442
|
+
|
443
|
+
corr2 = ncfile.createVariable(
|
444
|
+
"corr2", np.float32, ("time", "depth"), fill_value=-32768
|
445
|
+
)
|
446
|
+
corr2.long_name = "Beam 2 correlation"
|
447
|
+
|
448
|
+
corr3 = ncfile.createVariable(
|
449
|
+
"corr3", np.float32, ("time", "depth"), fill_value=-32768
|
450
|
+
)
|
451
|
+
corr3.long_name = "Beam 3 correlation"
|
452
|
+
|
453
|
+
corr4 = ncfile.createVariable(
|
454
|
+
"corr4", np.float32, ("time", "depth"), fill_value=-32768
|
455
|
+
)
|
456
|
+
corr4.long_name = "Beam 4 correlation"
|
457
|
+
|
458
|
+
pgd1 = ncfile.createVariable(
|
459
|
+
"pgd1", np.float32, ("time", "depth"), fill_value=-32768
|
460
|
+
)
|
461
|
+
pgd1.long_name = "Percent Good Beam 1"
|
462
|
+
|
463
|
+
pgd2 = ncfile.createVariable(
|
464
|
+
"pgd2", np.float32, ("time", "depth"), fill_value=-32768
|
465
|
+
)
|
466
|
+
pgd2.long_name = "Percent Good Beam 2"
|
467
|
+
|
468
|
+
pgd3 = ncfile.createVariable(
|
469
|
+
"pgd3", np.float32, ("time", "depth"), fill_value=-32768
|
470
|
+
)
|
471
|
+
pgd3.long_name = "Percent Good Beam 3"
|
472
|
+
|
473
|
+
pgd4 = ncfile.createVariable(
|
474
|
+
"pgd4", np.float32, ("time", "depth"), fill_value=-32768
|
475
|
+
)
|
476
|
+
pgd4.long_name = "Percent Good Beam 4"
|
477
|
+
|
310
478
|
nctime = pd2nctime(time, t0)
|
311
479
|
# write data
|
312
480
|
z[:] = depth
|
@@ -315,10 +483,25 @@ def finalnc(outfile, depth, time, data, t0="hours since 2000-01-01", attributes=
|
|
315
483
|
vvel[:, :] = data[1, :, :].T
|
316
484
|
wvel[:, :] = data[2, :, :].T
|
317
485
|
evel[:, :] = data[3, :, :].T
|
318
|
-
|
486
|
+
mvel[:, :] = final_mask.T
|
487
|
+
echo1[:, :] = final_echo[0, :, :].T
|
488
|
+
echo2[:, :] = final_echo[1, :, :].T
|
489
|
+
echo3[:, :] = final_echo[2, :, :].T
|
490
|
+
echo4[:, :] = final_echo[3, :, :].T
|
491
|
+
corr1[:, :] = final_corr[0, :, :].T
|
492
|
+
corr2[:, :] = final_corr[1, :, :].T
|
493
|
+
corr3[:, :] = final_corr[2, :, :].T
|
494
|
+
corr4[:, :] = final_corr[3, :, :].T
|
495
|
+
pgd1[:, :] = final_pgood[0, :, :].T
|
496
|
+
pgd2[:, :] = final_pgood[1, :, :].T
|
497
|
+
pgd3[:, :] = final_pgood[2, :, :].T
|
498
|
+
pgd4[:, :] = final_pgood[3, :, :].T
|
499
|
+
|
319
500
|
# Add global attributes if provided
|
320
501
|
if attributes:
|
321
502
|
for key, value in attributes.items():
|
322
503
|
setattr(ncfile, key, str(value)) # Store attributes as strings
|
323
504
|
|
505
|
+
ncfile.mask_applied = "True"
|
506
|
+
|
324
507
|
ncfile.close()
|