pyadps 0.2.1b0__py3-none-any.whl → 0.3.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.
@@ -1,20 +1,47 @@
1
1
  import numpy as np
2
2
  from pyadps.utils.plotgen import PlotNoise
3
+ from pyadps.utils.readrdi import ReadFile
3
4
 
4
5
 
5
6
  def qc_check(var, mask, cutoff=0):
6
7
  """
7
- The module returns the modified mask file after checking the cutoff criteria.
8
- All values less than the cuttoff are masked.
8
+ Perform a quality control check on the provided data and update the mask
9
+ based on a cutoff threshold. Values in `var` that are less than the cutoff
10
+ are marked as invalid in the mask.
9
11
 
10
- Args:
11
- var (numpy.ndarray):
12
- mask (numpy.ndarray): A mask file having same array size as var
13
- cutoff (int): Default cutoff is 0
12
+ Parameters
13
+ ----------
14
+ var : numpy.ndarray
15
+ The input array containing data to be checked against the cutoff.
16
+ mask : numpy.ndarray
17
+ An integer array of the same shape as `var`, where `1` indicates
18
+ invalid data and `0` indicates valid data.
19
+ cutoff : int, optional
20
+ The threshold value for quality control. Any value in `var` less than
21
+ or equal to this cutoff will be marked as invalid in the mask. Default is 0.
14
22
 
15
- Returns:
16
- mask (numpy.ndarray): Modified mask file based on cutoff
23
+ Returns
24
+ -------
25
+ numpy.ndarray
26
+ An updated integer mask array of the same shape as `var`, with `1`
27
+ indicating invalid data and `0` indicating valid data.
28
+
29
+ Notes
30
+ -----
31
+ - The function modifies the `mask` by applying the cutoff condition.
32
+ Values in `var` that are less than or equal to the cutoff will be
33
+ marked as invalid (`1`), while all other values will remain valid (`0`).
34
+ - Ensure that `var` and `mask` are compatible in shape for element-wise
35
+ operations.
36
+
37
+ Example
38
+ -------
39
+ >>> import pyadps
40
+ >>> ds = pyadps.Readfile('dummy.000')
41
+ >>> var = ds.echo.data
42
+ >>> mask = qc_check(var, mask, cutoff=40)
17
43
  """
44
+
18
45
  shape = np.shape(var)
19
46
  if len(shape) == 2:
20
47
  mask[var[:, :] < cutoff] = 1
@@ -22,16 +49,138 @@ def qc_check(var, mask, cutoff=0):
22
49
  beam = shape[0]
23
50
  for i in range(beam):
24
51
  mask[var[i, :, :] < cutoff] = 1
25
- values, counts = np.unique(mask, return_counts=True)
52
+ # values, counts = np.unique(mask, return_counts=True)
26
53
  # print(values, counts, np.round(counts[1] * 100 / np.sum(counts)))
27
54
  return mask
28
55
 
29
56
 
30
- cor_check = qc_check
31
- echo_check = qc_check
57
+ def correlation_check(ds, mask, cutoff=64):
58
+ """
59
+ Perform an correlation check on the provided variable and update the
60
+ mask to mark valid and invalid values based on a cutoff threshold.
61
+
62
+ Parameters
63
+ ----------
64
+ ds : pyadps.dataset
65
+ The input pyadps dataframe containing correlation data to be checked.
66
+ Accepts 2-D or 3-D masks.
67
+ mask : numpy.ndarray
68
+ An integer array of the same shape as `var`, where `1` indicates invalid
69
+ data or masked data and `0` indicates valid data.
70
+ cutoff : float, optional
71
+ The threshold value for echo intensity. Any value in `ds.correlation.data` below
72
+ this cutoff will be considered invalid and marked as `1` in the mask.
73
+ Default is 64.
74
+
75
+ Returns
76
+ -------
77
+ numpy.ndarray
78
+ An updated integer mask array of the same shape as `var`, with `1`
79
+ indicating invalid or masked data (within the cutoff limit) and `0` indicating
80
+ valid.
81
+
82
+ Notes
83
+ -----
84
+ - The function modifies the `mask` based on the cutoff condition. Valid
85
+ values in `var` retain their corresponding mask value as `0`, while
86
+ invalid values or previously masked elements are marked as `1`.
87
+ operations.
88
+
89
+ Example
90
+ -------
91
+ >>> import pyadps
92
+ >>> ds = pyadps.Readfile('dummy.000')
93
+ >>> outmask = correlation_check(ds, mask, cutoff=9999)
94
+ """
95
+ correlation = ds.correlation.data
96
+ mask = qc_check(correlation, mask, cutoff=cutoff)
97
+ return mask
98
+
99
+ def echo_check(ds, mask, cutoff=40):
100
+ """
101
+ Perform an echo intensity check on the provided variable and update the
102
+ mask to mark valid and invalid values based on a cutoff threshold.
103
+
104
+ Parameters
105
+ ----------
106
+ ds : pyadps.dataset
107
+ The input pyadps dataframe containing echo intensity data to be checked.
108
+ Accepts 2-D or 3-D masks.
109
+ mask : numpy.ndarray
110
+ An integer array of the same shape as `var`, where `1` indicates invalid
111
+ data or masked data and `0` indicates valid data.
112
+ cutoff : float, optional
113
+ The threshold value for echo intensity. Any value in `ds.echo.data` below
114
+ this cutoff will be considered invalid and marked as `1` in the mask.
115
+ Default is 40.
116
+
117
+ Returns
118
+ -------
119
+ numpy.ndarray
120
+ An updated integer mask array of the same shape as `var`, with `1`
121
+ indicating invalid or masked data (within the cutoff limit) and `0` indicating
122
+ valid.
32
123
 
124
+ Notes
125
+ -----
126
+ - The function modifies the `mask` based on the cutoff condition. Valid
127
+ values in `var` retain their corresponding mask value as `0`, while
128
+ invalid values or previously masked elements are marked as `1`.
129
+ - Ensure that `var` and `mask` are compatible in shape for element-wise
130
+ operations.
33
131
 
34
- def ev_check(var, mask, cutoff=9999):
132
+ Example
133
+ -------
134
+ >>> import pyadps
135
+ >>> ds = pyadps.Readfile('dummy.000')
136
+ >>> outmask = echo_check(ds, mask, cutoff=9999)
137
+ """
138
+
139
+ echo = ds.echo.data
140
+ mask = qc_check(echo, mask, cutoff=cutoff)
141
+ return mask
142
+
143
+
144
+ def ev_check(ds, mask, cutoff=9999):
145
+ """
146
+ Perform an error velocity check on the provided variable and update the
147
+ mask to mark valid and invalid values based on a cutoff threshold.
148
+
149
+ Parameters
150
+ ----------
151
+ ds : pyadps.dataset
152
+ The input pyadps dataframe containing error velocity data to be checked.
153
+ mask : numpy.ndarray
154
+ An integer array of the same shape as `var`, where `1` indicates invalid
155
+ data or masked data and `0` indicates valid data.
156
+ cutoff : float, optional
157
+ The threshold value for error velocity. Any value in `var` exceeding
158
+ this cutoff will be considered invalid and marked as `0` in the mask.
159
+ Default is 9999.
160
+
161
+ Returns
162
+ -------
163
+ numpy.ndarray
164
+ An updated integer mask array of the same shape as `var`, with `1`
165
+ indicating invalid or masked data (within the cutoff limit) and `0` indicating
166
+ valid.
167
+
168
+ Notes
169
+ -----
170
+ - The function modifies the `mask` based on the cutoff condition. Valid
171
+ values in `var` retain their corresponding mask value as `0`, while
172
+ invalid values or previously masked elements are marked as `1`.
173
+ - Ensure that `var` and `mask` are compatible in shape for element-wise
174
+ operations.
175
+
176
+ Example
177
+ -------
178
+ >>> import pyadps
179
+ >>> ds = pyadps.Readfile('dummy.000')
180
+ >>> outmask = ev_check(ds, mask, cutoff=9999)
181
+ """
182
+
183
+ var = ds.velocity.data[3, :, :]
35
184
  shape = np.shape(var)
36
185
  var = abs(var)
37
186
  if len(shape) == 2:
@@ -40,24 +189,110 @@ def ev_check(var, mask, cutoff=9999):
40
189
  beam = shape[2]
41
190
  for i in range(beam):
42
191
  mask[(var[i, :, :] >= cutoff) & (var[i, :, :] < 32768)] = 1
43
- values, counts = np.unique(mask, return_counts=True)
44
- # print(values, counts, np.round(counts[1] * 100 / np.sum(counts)))
45
192
  return mask
46
193
 
47
194
 
48
- def pg_check(pgood, mask, cutoff=0, threebeam=True):
195
+ def pg_check(ds, mask, cutoff=0, threebeam=True):
196
+ """
197
+ Perform a percent-good check on the provided data and update the mask
198
+ to mark valid and invalid values based on a cutoff threshold.
199
+
200
+ Parameters
201
+ ----------
202
+ ds : pyadps.dataset
203
+ The input pyadps dataframe containing percent-good data, where values range from
204
+ 0 to 100 (maximum percent good).
205
+ mask : numpy.ndarray
206
+ An integer array of the same shape as `pgood`, where `1` indicates
207
+ invalid data and `0` indicates valid data.
208
+ cutoff : float, optional
209
+ The threshold value for percent good. Any value in `pgood` greater than
210
+ or equal to this cutoff will be considered valid (marked as `0`),
211
+ while values not exceeding the cutoff are marked as invalid (`1`).
212
+ Default is 0.
213
+ threebeam : bool, optional
214
+ If `True`, sums up Percent Good 1 and Percent Good 4 for the check.
215
+
216
+ Returns
217
+ -------
218
+ numpy.ndarray
219
+ An updated integer mask array of the same shape as `pgood`, with `1`
220
+ indicating invalid data and `0` indicating valid data.
221
+
222
+ Notes
223
+ -----
224
+ - The function modifies the `mask` based on the cutoff condition. Valid
225
+ values in `pgood` are marked as `0`, while invalid values are marked
226
+ as `1` in the mask.
227
+ - Ensure that `pgood` and `mask` are compatible in shape for element-wise
228
+ operations.
229
+ - If `threebeam` is `True`, the logic may be adjusted to allow partial
230
+ validity based on specific criteria.
231
+
232
+ Example
233
+ -------
234
+ >>> import pyadps
235
+ >>> ds = pyadps.Readfile('dummy.000')
236
+ >>> outmask = pg_check(ds, mask, cutoff=50, threebeam=True)
237
+ """
238
+
239
+ pgood = ds.percentgood.data
49
240
  if threebeam:
50
241
  pgood1 = pgood[0, :, :] + pgood[3, :, :]
51
242
  else:
52
243
  pgood1 = pgood[:, :, :]
53
244
 
54
245
  mask[pgood1[:, :] < cutoff] = 1
55
- values, counts = np.unique(mask, return_counts=True)
56
- # print(values, counts, np.round(counts[1] * 100 / np.sum(counts)))
57
246
  return mask
58
247
 
59
248
 
60
- def false_target(echo, mask, cutoff=255, threebeam=True):
249
+ def false_target(ds, mask, cutoff=255, threebeam=True):
250
+ """
251
+ Apply a false target detection algorithm based on echo intensity values.
252
+ This function identifies invalid or false targets in the data and updates
253
+ the mask accordingly based on a specified cutoff threshold.
254
+
255
+ Parameters
256
+ ----------
257
+ ds : pyadps.dataset
258
+ The input pyadps dataframe containing echo intensity values, which are used to
259
+ detect false targets.
260
+ mask : numpy.ndarray
261
+ An integer array of the same shape as `echo`, where `1` indicates
262
+ invalid or false target data and `0` indicates valid data.
263
+ cutoff : int, optional
264
+ The threshold value for echo intensity. Any value in `echo` greater
265
+ than or equal to this cutoff will be considered a false target (invalid),
266
+ marked as `1` in the mask. Default is 255.
267
+ threebeam : bool, optional
268
+ If `True`, applies a relaxed check that considers data valid even
269
+ when only three beams report valid data. Default is `True`.
270
+
271
+ Returns
272
+ -------
273
+ numpy.ndarray
274
+ An updated integer mask array of the same shape as `echo`, with `1`
275
+ indicating false target or invalid data and `0` indicating valid data.
276
+
277
+ Notes
278
+ -----
279
+ - The function modifies the `mask` by applying the cutoff condition.
280
+ Echo values greater than or equal to the cutoff are marked as false
281
+ targets (`1`), while values below the cutoff are considered valid (`0`).
282
+ - If `threebeam` is `True`, a more lenient check may be applied to handle
283
+ data with fewer valid beams.
284
+ - Ensure that `echo` and `mask` are compatible in shape for element-wise
285
+ operations.
286
+
287
+ Example
288
+ -------
289
+ >>> import pyadps
290
+ >>> ds = pyadps.Readfile('dummy.000')
291
+ >>> mask = false_target(echo, mask, cutoff=255)
292
+ """
293
+
294
+ echo = ds.echo.data
295
+
61
296
  shape = np.shape(echo)
62
297
  for i in range(shape[1]):
63
298
  for j in range(shape[2]):
@@ -74,10 +309,49 @@ def false_target(echo, mask, cutoff=255, threebeam=True):
74
309
  return mask
75
310
 
76
311
 
77
- def default_mask(flobj, velocity):
78
- cells = flobj.field()["Cells"]
79
- beams = flobj.field()["Beams"]
80
- ensembles = flobj.ensembles
312
+ def default_mask(ds):
313
+ """
314
+ Create a default 2-D mask file based on the velocity data.
315
+ This function generates a mask where values are marked as valid or invalid
316
+ based on the missing values from the velocity data.
317
+
318
+ Parameters
319
+ ----------
320
+ ds : pyadps.dataset or numpy.ndarray
321
+ A pyadps data frame is used to extract velocity and dimensions for the mask.
322
+ If numpy.ndarray, enter the values for beams, cells and ensembles.
323
+
324
+ Returns
325
+ -------
326
+ numpy.ndarray
327
+ A mask array of the same shape as `velocity`, where `1` indicates invalid
328
+ data and `0` indicates valid data.
329
+
330
+ Notes
331
+ -----
332
+ - The function uses the velocity data along with the information from the
333
+ Fixed Leader object to determine which values are valid and which are invalid.
334
+
335
+ Example
336
+ -------
337
+ >>> import pyadps
338
+ >>> ds = pyadps.ReadFile('demo.000')
339
+ >>> mask = pyadps.default_mask(ds)
340
+ """
341
+ if isinstance(ds, ReadFile) or ds.__class__.__name__ == "ReadFile":
342
+ flobj = ds.fixedleader
343
+ velocity = ds.velocity.data
344
+ cells = flobj.field()["Cells"]
345
+ beams = flobj.field()["Beams"]
346
+ ensembles = flobj.ensembles
347
+ elif isinstance(ds, np.ndarray) and ds.ndim == 3:
348
+ velocity = ds
349
+ beams = ds.shape[0]
350
+ cells = ds.shape[1]
351
+ ensembles = ds.shape[2]
352
+ else:
353
+ raise ValueError("Input must be a 3-D numpy array or a PyADPS instance")
354
+
81
355
  mask = np.zeros((cells, ensembles))
82
356
  # Ignore mask for error velocity
83
357
  for i in range(beams - 1):
@@ -85,7 +359,53 @@ def default_mask(flobj, velocity):
85
359
  return mask
86
360
 
87
361
 
88
- def qc_prompt(flobj, name, data=None):
362
+ def qc_prompt(ds, name, data=None):
363
+ """
364
+ Prompt the user to confirm or adjust the quality control threshold for a specific
365
+ parameter based on predefined ranges. The function provides an interactive interface
366
+ for the user to adjust thresholds for various quality control criteria, with options
367
+ for certain thresholds like "Echo Intensity Thresh" to check the noise floor.
368
+
369
+ Parameters
370
+ ----------
371
+ flobj : FixedLeader
372
+ An instance of the FixedLeader class that holds metadata and configuration
373
+ data. The `flobj` is used to retrieve the current threshold values based on
374
+ the provided parameter name.
375
+ name : str
376
+ The name of the parameter for which the threshold is being adjusted. Examples
377
+ include "Echo Intensity Thresh", "Correlation Thresh", "Percent Good Min", etc.
378
+ data : numpy.ndarray, optional
379
+ The data associated with the threshold. This is required for parameters like
380
+ "Echo Intensity Thresh" where a noise floor check might be performed. Default is None.
381
+
382
+ Returns
383
+ -------
384
+ int
385
+ The updated threshold value, either the default or the new value entered by the user.
386
+
387
+ Notes
388
+ -----
389
+ - The function will prompt the user to change the threshold for the given `name` parameter.
390
+ - For certain parameters, the user may be asked if they would like to check the noise floor
391
+ (for example, for "Echo Intensity Thresh"). This triggers the display of a plot and lets
392
+ the user select a new threshold.
393
+ - The function ensures that the new threshold is within the acceptable range for each parameter.
394
+ - The default thresholds are provided if the user chooses not to change them.
395
+
396
+ Example
397
+ -------
398
+ >>> import pyadps
399
+ >>> ds = pyadps.ReadFile('demo.000')
400
+ >>> name = "Echo Intensity Thresh"
401
+ >>> threshold = qc_prompt(ds, name, data)
402
+ The default threshold for echo intensity thresh is 0
403
+ Would you like to change the threshold [y/n]: y
404
+ Would you like to check the noise floor [y/n]: y
405
+ Threshold changed to 50
406
+ """
407
+
408
+ flobj = ds.fixedleader
89
409
  cutoff = 0
90
410
  if name == "Echo Intensity Thresh":
91
411
  cutoff = 0
@@ -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
- baseurl = "https://www.ngdc.noaa.gov/geomag-web/calculators/calculateDeclination?"
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
- url = "{}lat1={}&lon1={}&key={}&startYear{}&resultFormat={}".format(baseurl, lat1, lon1, key, year, resultFormat)
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
- Returns:
45
- mag: Magnetic declination (degrees)
46
- """
47
- import wmm2020
48
- mag = wmm2020.wmm(lat, lon, depth, year)
49
- mag = mag.decl.data
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(mag)
68
- velocity[1, :, :] = -1 * velocity[0, :, :] * np.sin(mag) + velocity[1, :, :] * np.cos(mag)
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, kernal_size=13, cutoff=150):
135
+ def despike(velocity, mask, kernal_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,19 +140,24 @@ 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
- kernal_size (paramater, integer): Number of ensembles over which the spike has to be checked
101
- cutoff (parameter, integer): [TODO:description]
143
+ kernal_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]):
152
+ # Apply median filter
110
153
  filt = sp.signal.medfilt(velocity[j, :], kernal_size)
154
+ # Calculate absolute deviation from the rolling median
111
155
  diff = np.abs(velocity[j, :] - filt)
112
- mask[j, :] = np.where(diff < cutoff, mask[j, :], 1)
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
 
pyadps/utils/writenc.py CHANGED
@@ -244,7 +244,7 @@ def vlead_nc(infile, outfile, time, axis_option=None, attributes=None, t0="hours
244
244
  outnc.close()
245
245
 
246
246
 
247
- def finalnc(outfile, depth, time, data, t0="hours since 2000-01-01", attributes=None):
247
+ def finalnc(outfile, depth, final_mask, time, data, t0="hours since 2000-01-01", attributes=None):
248
248
  """
249
249
  Function to create the processed NetCDF file.
250
250
 
@@ -268,6 +268,7 @@ def finalnc(outfile, depth, time, data, t0="hours since 2000-01-01", attributes=
268
268
  if np.all(depth[:-1] >= depth[1:]):
269
269
  depth = depth[::-1]
270
270
  data = data[:, ::-1, :]
271
+ final_mask = final_mask[::-1, :]
271
272
 
272
273
  ncfile = nc4.Dataset(outfile, mode="w", format="NETCDF4")
273
274
  # Check if depth is scalar or array
@@ -307,6 +308,9 @@ def finalnc(outfile, depth, time, data, t0="hours since 2000-01-01", attributes=
307
308
  evel.units = "cm/s"
308
309
  evel.long_name = "error_velocity"
309
310
 
311
+ mvel = ncfile.createVariable("mask", np.float32, ("time", "depth"), fill_value=fill)
312
+ mvel.long_name = "Velocity Mask (1: bad value, 0: good value)"
313
+
310
314
  nctime = pd2nctime(time, t0)
311
315
  # write data
312
316
  z[:] = depth
@@ -315,10 +319,13 @@ def finalnc(outfile, depth, time, data, t0="hours since 2000-01-01", attributes=
315
319
  vvel[:, :] = data[1, :, :].T
316
320
  wvel[:, :] = data[2, :, :].T
317
321
  evel[:, :] = data[3, :, :].T
322
+ mvel[:, :] = final_mask.T
318
323
 
319
324
  # Add global attributes if provided
320
325
  if attributes:
321
326
  for key, value in attributes.items():
322
327
  setattr(ncfile, key, str(value)) # Store attributes as strings
328
+
329
+ ncfile.mask_applied = "True"
323
330
 
324
331
  ncfile.close()
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: pyadps
3
- Version: 0.2.1b0
3
+ Version: 0.3.0b0
4
4
  Summary: A Python package for ADCP data processing
5
5
  Home-page: https://example.com
6
6
  License: MIT
@@ -22,9 +22,9 @@ Requires-Dist: numpy (>=1.26.4)
22
22
  Requires-Dist: pandas (>=2.2.2)
23
23
  Requires-Dist: plotly (>=5.22.0)
24
24
  Requires-Dist: plotly-resampler (>=0.10.0)
25
+ Requires-Dist: pygeomag (>=1.1.0,<2.0.0)
25
26
  Requires-Dist: scipy (>=1.14.0)
26
27
  Requires-Dist: streamlit (>=1.36.0)
27
- Requires-Dist: wmm2020 (>=1.1.1)
28
28
  Project-URL: Documentation, https://example.com/docs
29
29
  Project-URL: Repository, https://github.com/p-amol/pyadps
30
30
  Description-Content-Type: text/markdown
@@ -0,0 +1,33 @@
1
+ pyadps/Home_Page.py,sha256=gC0eFMtn85U_A4KcVlCEzXkB6a_J0WD3vpK691Kmyw8,1180
2
+ pyadps/__init__.py,sha256=bNCm6_WIhiwvaUeOZhRkyLZyzzUKfSH80Fslg0JPJyk,232
3
+ pyadps/__main__.py,sha256=cIFUayxPnKl00oIR99L6IUEvc8trW7dijtfBQCAen5c,356
4
+ pyadps/pages/01_Read_File.py,sha256=VfzxaOETEAdIJwth6QPiqDLgWtPc-nZf30huJR1velM,11611
5
+ pyadps/pages/02_View_Raw_Data.py,sha256=AhT7gvDbcMRPf-WIBzTQ0o-nn9_q7NH6plTlpMtgzaY,6170
6
+ pyadps/pages/03_Download_Raw_File.py,sha256=6tv1b5zyImSOVkTVhhGpm2TUVkvanhlTUksUlKJMWC8,8791
7
+ pyadps/pages/04_Sensor_Health.py,sha256=2abiawkByeOIx8h2B2-cm_UVL--dKWR7OWkZHu6TnY0,33499
8
+ pyadps/pages/05_QC_Test.py,sha256=kHTB4X3trKjLjT2pgIKzHMRCR2MvRf23V6BaThieAPU,16043
9
+ pyadps/pages/06_Profile_Test.py,sha256=bjfEqTwYUTdpFPf8ovEIqiz7O5pP_Y4Kxnj6AidF0FE,34163
10
+ pyadps/pages/07_Velocity_Test.py,sha256=mFYjXaswTZNkpWd9k2peq96uPBj-oTd6QYE7J8eQSHY,22792
11
+ pyadps/pages/08_Write_File.py,sha256=GrAo2KVOck2DYSp0x3Lb1pdYL-lZF8SBEdyDT7ev_j0,19542
12
+ pyadps/pages/09_Auto_process.py,sha256=gOvLEfwAPxe9v-W8DASKSuNQzB5BjHLnPkwUgOufwdI,1776
13
+ pyadps/pages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ pyadps/utils/__init__.py,sha256=v1FzqeMdtqNlZfYN_Hzl7oNtMLkJacT-vATgz45hhno,373
15
+ pyadps/utils/autoprocess.py,sha256=aLsbLD5CoZ7bz1p737g01w1ym8BjEZjZpgGzLrngdUM,13825
16
+ pyadps/utils/metadata/config.ini,sha256=TC7htzGwUukIXt_u3JR5ycyvOoDj_JxWgGY6khjNeck,2154
17
+ pyadps/utils/metadata/demo.000,sha256=qxB3sgjABrpv4DNXkwjpbSxk5sc4UwAI8kgQX0--PM8,234468
18
+ pyadps/utils/metadata/flmeta.json,sha256=diIB9nht_0uw9YJNSFGdZYGzeVbR-07zIZS9Nf4VPSE,14245
19
+ pyadps/utils/metadata/vlmeta.json,sha256=_dkQlGkkUvpAIM7S6kEUenSaiCpOrwXg8n1aU3dDF3s,22535
20
+ pyadps/utils/plotgen.py,sha256=YsOetfczZ6NQMcLDZGMs_GsOT4AISsyaBA62rq7-CdM,26228
21
+ pyadps/utils/profile_test.py,sha256=RRTDJNKeUG8mJWFDhVJpBQQNidLG5C06pOT8XbWeeXE,20401
22
+ pyadps/utils/pyreadrdi.py,sha256=P1UTDrglgbYn3XQGUTsqNPynDGE-zp4cI_TW8yfOlic,35090
23
+ pyadps/utils/readrdi.py,sha256=36GfMn3bLQis8PsrL3zlAC22rBU9ItosWug3_44yesg,47403
24
+ pyadps/utils/script.py,sha256=RCRPm1s_HJpqWRO-E316WmFkONv9lkp2tzzvPGF2-I4,4919
25
+ pyadps/utils/sensor_health.py,sha256=aHRaU4kMJZ9dGmYypKpCCgq-owWoNjvcl1I_9I7dG68,3973
26
+ pyadps/utils/signal_quality.py,sha256=ab0Sr0oPFxkFWBjuGbl_IZNQEnfi_mXPyHmVzaGSOBU,16239
27
+ pyadps/utils/velocity_test.py,sha256=-95NKLQJ8Ni8etdxhDHxsfMF4MdRWcXL9fgLgWy7Kn0,6112
28
+ pyadps/utils/writenc.py,sha256=WrL5uh--qPLTPo-f2b49j0Ozm7Fq6H-97AJe4KMWkyE,10071
29
+ pyadps-0.3.0b0.dist-info/LICENSE,sha256=sfY_7DzQF5FxnO2T6ek74dfm5uBmwEp1oEg_WlzNsb8,1092
30
+ pyadps-0.3.0b0.dist-info/METADATA,sha256=RiQu9cwuLigYrVrbkjr9I9nfJh2Jrdaj2chl8aiSZG4,4463
31
+ pyadps-0.3.0b0.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
32
+ pyadps-0.3.0b0.dist-info/entry_points.txt,sha256=qS5lbmTJLC4Ys0nu4-2tJoBpAHxTREta30KFrDyTfsY,90
33
+ pyadps-0.3.0b0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.1
2
+ Generator: poetry-core 2.0.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any