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.
- pyadps/pages/01_Read_File.py +2 -0
- pyadps/pages/03_Download_Raw_File.py +22 -9
- pyadps/pages/04_QC_Test.py +56 -5
- pyadps/pages/05_Profile_Test.py +203 -17
- pyadps/pages/06_Velocity_Test.py +67 -19
- pyadps/pages/07_Write_File.py +138 -53
- pyadps/utils/__init__.py +1 -1
- pyadps/utils/autoprocess.py +282 -0
- pyadps/utils/metadata/config.ini +81 -0
- pyadps/utils/profile_test.py +36 -24
- pyadps/utils/readrdi.py +3 -2
- pyadps/utils/regrid.py +211 -54
- pyadps/utils/velocity_test.py +50 -15
- pyadps/utils/writenc.py +82 -20
- {pyadps-0.1.0b0.dist-info → pyadps-0.2.0b0.dist-info}/METADATA +2 -1
- pyadps-0.2.0b0.dist-info/RECORD +31 -0
- {pyadps-0.1.0b0.dist-info → pyadps-0.2.0b0.dist-info}/WHEEL +1 -1
- {pyadps-0.1.0b0.dist-info → pyadps-0.2.0b0.dist-info}/entry_points.txt +1 -0
- pyadps-0.1.0b0.dist-info/RECORD +0 -29
- {pyadps-0.1.0b0.dist-info → pyadps-0.2.0b0.dist-info}/LICENSE +0 -0
pyadps/utils/profile_test.py
CHANGED
@@ -2,8 +2,8 @@ import matplotlib.pyplot as plt
|
|
2
2
|
import numpy as np
|
3
3
|
import streamlit as st
|
4
4
|
from matplotlib.widgets import Button, Slider, TextBox
|
5
|
-
|
6
5
|
from pyadps.utils import readrdi as rd
|
6
|
+
|
7
7
|
from .plotgen import plotmask, plotvar
|
8
8
|
|
9
9
|
|
@@ -127,7 +127,7 @@ def trim_ends(vlobj, mask, method="Manual"):
|
|
127
127
|
return mask
|
128
128
|
|
129
129
|
|
130
|
-
def side_lobe_beam_angle(flobj, vlobj, mask, extra_cells=2):
|
130
|
+
def side_lobe_beam_angle(flobj, vlobj, mask, orientation='default', water_column_depth=0, extra_cells=2):
|
131
131
|
beam_angle = int(flobj.system_configuration()["Beam Angle"])
|
132
132
|
cell_size = flobj.field()["Depth Cell Len"]
|
133
133
|
bin1dist = flobj.field()["Bin 1 Dist"]
|
@@ -135,11 +135,19 @@ def side_lobe_beam_angle(flobj, vlobj, mask, extra_cells=2):
|
|
135
135
|
ensembles = flobj.ensembles
|
136
136
|
transducer_depth = vlobj.vleader["Depth of Transducer"]
|
137
137
|
|
138
|
+
if orientation.lower() == "default":
|
139
|
+
orientation = flobj.system_configuration()['Beam Direction']
|
140
|
+
|
141
|
+
if orientation.lower() == "up":
|
142
|
+
sgn = -1
|
143
|
+
water_column_depth = 0
|
144
|
+
else:
|
145
|
+
sgn = 1
|
146
|
+
|
138
147
|
beam_angle = np.deg2rad(beam_angle)
|
139
148
|
depth = transducer_depth / 10
|
140
|
-
valid_depth = depth * np.cos(beam_angle)
|
149
|
+
valid_depth = (water_column_depth - sgn*depth) * np.cos(beam_angle) + sgn*bin1dist / 100
|
141
150
|
valid_cells = np.trunc(valid_depth * 100 / cell_size) - extra_cells
|
142
|
-
st.write(cells, valid_cells[100], extra_cells)
|
143
151
|
|
144
152
|
for i in range(ensembles):
|
145
153
|
c = int(valid_cells[i])
|
@@ -153,23 +161,27 @@ def side_lobe_rssi_bump(echo, mask):
|
|
153
161
|
pass
|
154
162
|
|
155
163
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
#
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
164
|
+
def manual_cut_bins(mask, min_cell, max_cell, min_ensemble, max_ensemble):
|
165
|
+
"""
|
166
|
+
Apply manual bin cutting by selecting a specific range of cells and ensembles.
|
167
|
+
|
168
|
+
Parameters:
|
169
|
+
mask (numpy array): The mask array to modify.
|
170
|
+
min_cell (int): The minimum cell index to mask.
|
171
|
+
max_cell (int): The maximum cell index to mask.
|
172
|
+
min_ensemble (int): The minimum ensemble index to mask.
|
173
|
+
max_ensemble (int): The maximum ensemble index to mask.
|
174
|
+
|
175
|
+
Returns:
|
176
|
+
numpy array: The updated mask with selected areas masked.
|
177
|
+
"""
|
178
|
+
# Ensure the indices are within valid range
|
179
|
+
min_cell = max(0, min_cell)
|
180
|
+
max_cell = min(mask.shape[0], max_cell)
|
181
|
+
min_ensemble = max(0, min_ensemble)
|
182
|
+
max_ensemble = min(mask.shape[1], max_ensemble)
|
183
|
+
|
184
|
+
# Apply mask on the selected range
|
185
|
+
mask[min_cell:max_cell, min_ensemble:max_ensemble] = 1
|
186
|
+
|
187
|
+
return mask
|
pyadps/utils/readrdi.py
CHANGED
@@ -326,7 +326,7 @@ class FileHeader:
|
|
326
326
|
"""
|
327
327
|
file_stats = os.stat(self.filename)
|
328
328
|
sys_file_size = file_stats.st_size
|
329
|
-
cal_file_size = sum(self.bytes) + 2 * len(self.bytes)
|
329
|
+
cal_file_size = sum((self.bytes).astype(int)) + 2 * len(self.bytes)
|
330
330
|
|
331
331
|
check = dict()
|
332
332
|
|
@@ -800,7 +800,8 @@ def vlead_dict(vid):
|
|
800
800
|
|
801
801
|
counter = 1
|
802
802
|
for key, value in vname.items():
|
803
|
-
vlead[key] = getattr(np, value)(vid[:][counter])
|
803
|
+
# vlead[key] = getattr(np, value)(vid[:][counter])
|
804
|
+
vlead[key] = vid[:][counter]
|
804
805
|
counter += 1
|
805
806
|
|
806
807
|
return vlead
|
pyadps/utils/regrid.py
CHANGED
@@ -9,49 +9,148 @@ def regrid2d(
|
|
9
9
|
vlobj,
|
10
10
|
data,
|
11
11
|
fill_value,
|
12
|
-
|
12
|
+
end_bin_option="cell",
|
13
13
|
trimends=None,
|
14
14
|
method="nearest",
|
15
|
+
orientation="default",
|
16
|
+
boundary_limit=0,
|
15
17
|
):
|
16
|
-
|
18
|
+
"""
|
19
|
+
Regrids 2D data onto a new grid based on specified parameters.
|
20
|
+
|
21
|
+
Parameters:
|
22
|
+
-----------
|
23
|
+
flobj : object
|
24
|
+
The fixed leader object that contains information
|
25
|
+
about the fixed leader data.
|
26
|
+
|
27
|
+
vlobj : object
|
28
|
+
The variable leader object that contains information
|
29
|
+
about the variable leader data.
|
30
|
+
|
31
|
+
data : array-like
|
32
|
+
The 2D data array to be regridded.
|
33
|
+
|
34
|
+
fill_value : scalar
|
35
|
+
The value used to fill missing or undefined grid points.
|
36
|
+
|
37
|
+
end_bin_option : str or float, optional, default="cell"
|
38
|
+
The depth of the last bin or boundary for the grid.
|
39
|
+
Options include:
|
40
|
+
- "cell" : Calculates the depth of the default last bin for the grid.
|
41
|
+
Truncates to surface for upward ADCP.
|
42
|
+
- "surface": The data is gridded till the surface
|
43
|
+
- "manual": User-defined depth for the grid.
|
44
|
+
Use boundary_limit option to provide the value.
|
45
|
+
otherwise, a specific numerical depth value can be provided.
|
46
|
+
|
47
|
+
trimends : tuple of floats, optional, default=None
|
48
|
+
If provided, defines the ensemble range (start, end) for
|
49
|
+
calculating the maximum/minimum transducer depth.
|
50
|
+
Helps avoiding the deployment or retrieval data.
|
51
|
+
E.g. (10, 3000)
|
52
|
+
|
53
|
+
method : str, optional, default="nearest"
|
54
|
+
The interpolation method to use for regridding based
|
55
|
+
on scipy.interpolate.interp1d.
|
56
|
+
Options include:
|
57
|
+
- "nearest" : Nearest neighbor interpolation.
|
58
|
+
- "linear" : Linear interpolation.
|
59
|
+
- "cubic" : Cubic interpolation.
|
60
|
+
|
61
|
+
orientation : str, optional, default="up"
|
62
|
+
Defines the direction of the regridding for an upward/downward looking ADCP. Options include:
|
63
|
+
- "up" : Regrid upwards (for upward-looking ADCP).
|
64
|
+
- "down" : Regrid downwards (for downward-looking ADCP).
|
65
|
+
|
66
|
+
boundary_limit : float, optional, default=0
|
67
|
+
The limit for the boundary depth. This restricts the grid regridding to depths beyond the specified limit.
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
--------
|
71
|
+
z: regridded depth
|
72
|
+
regridded_data : array-like
|
73
|
+
The regridded 2D data array, based on the specified method,
|
74
|
+
orientation, and other parameters.
|
75
|
+
|
76
|
+
Notes:
|
77
|
+
------
|
78
|
+
- If `end_bin_option == boundary`, then `boundary_limit` is used to regrid the data.
|
79
|
+
- This function allows for flexible regridding of 2D data to fit a new grid, supporting different interpolation methods.
|
80
|
+
- The `boundary_limit` parameter helps restrict regridding to depths above or below a certain threshold.
|
81
|
+
"""
|
82
|
+
|
83
|
+
# Get values and convert to 'm'
|
84
|
+
bin1dist = flobj.field()["Bin 1 Dist"] / 100
|
85
|
+
transdepth = vlobj.vleader["Depth of Transducer"] / 10
|
17
86
|
depth_interval = flobj.field()["Depth Cell Len"] / 100
|
18
87
|
bins = flobj.field()["Cells"]
|
19
88
|
ensembles = flobj.ensembles
|
20
89
|
|
90
|
+
if orientation.lower() == "default":
|
91
|
+
orientation = flobj.system_configuration()['Beam Direction']
|
92
|
+
|
93
|
+
if orientation.lower() == "up":
|
94
|
+
sgn = -1
|
95
|
+
else:
|
96
|
+
sgn = 1
|
97
|
+
|
21
98
|
# Create a regular grid
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
mindepth = mintransdepth - mintransdepth % depth_interval
|
32
|
-
mindepth = mindepth - depth_interval
|
33
|
-
# If mindepth is above surface choose surface
|
34
|
-
if mindepth < 0:
|
35
|
-
mindepth = depth_interval
|
99
|
+
|
100
|
+
# Find depth of first cell
|
101
|
+
depth = transdepth + sgn*bin1dist
|
102
|
+
|
103
|
+
# Find the maximum and minimum depth for first cell for upward
|
104
|
+
# looking ADCP (minimum and maximum for downward looking)
|
105
|
+
if trimends is not None:
|
106
|
+
max_depth = abs(np.min(sgn*depth[trimends[0] : trimends[1]]))
|
107
|
+
min_depth = abs(np.max(sgn*depth[trimends[0] : trimends[1]]))
|
36
108
|
else:
|
37
|
-
|
109
|
+
max_depth = abs(np.min(sgn*depth))
|
110
|
+
min_depth = abs(np.max(sgn*depth))
|
38
111
|
|
39
|
-
|
40
|
-
#
|
41
|
-
|
42
|
-
# maxbins = maxbins + 1
|
112
|
+
# FIRST CELL
|
113
|
+
# Convert the first cell depth to the first regular grid depth
|
114
|
+
depthfirstcell = max_depth - max_depth % depth_interval
|
43
115
|
|
44
|
-
|
45
|
-
|
116
|
+
# LAST CELL
|
117
|
+
# Convert the last cell depth to last regular grid depth
|
118
|
+
if end_bin_option.lower() == "surface":
|
119
|
+
# Added one additional negative cell to accomodate 0 m.
|
120
|
+
depthlastcell = sgn * depth_interval
|
121
|
+
elif end_bin_option.lower() == "cell":
|
122
|
+
min_depth_regrid = min_depth - sgn*min_depth % depth_interval
|
123
|
+
depthlastcell = min_depth_regrid + sgn* (bins+1) * depth_interval
|
124
|
+
# Check if this is required. Use 'surface' option
|
125
|
+
if depthlastcell < 0:
|
126
|
+
depthlastcell = sgn*depth_interval
|
127
|
+
elif end_bin_option.lower() == "manual":
|
128
|
+
if sgn < 0 and boundary_limit > depthfirstcell:
|
129
|
+
print("ERROR: For upward looking ADCP, boundary limit should be less than transducer depth")
|
130
|
+
return
|
131
|
+
if sgn > 0 and boundary_limit < depthfirstcell:
|
132
|
+
print("ERROR: For downward looking ADCP, boundary limit should be greater than transducer depth")
|
133
|
+
return
|
134
|
+
# Set the last grid cell depth
|
135
|
+
depthlastcell = boundary_limit
|
136
|
+
else:
|
137
|
+
print("ERROR: `end_bin_option` not recognized.")
|
138
|
+
return
|
139
|
+
|
140
|
+
# Negative used for upward and positive for downward.
|
141
|
+
z = np.arange(sgn * depthfirstcell, sgn * depthlastcell, depth_interval)
|
46
142
|
regbins = len(z)
|
47
143
|
|
48
|
-
|
49
|
-
data_regrid = np.zeros((regbins, ensembles))
|
144
|
+
regridded_data = np.zeros((regbins, ensembles))
|
50
145
|
|
51
146
|
# Create original depth array
|
52
147
|
for i, d in enumerate(depth):
|
53
|
-
n =
|
54
|
-
|
148
|
+
n = d + sgn*depth_interval * bins
|
149
|
+
# np.arange may include unexpected elements due to floating-point
|
150
|
+
# precision issues at the stopping point. Changed to np.linspace.
|
151
|
+
#
|
152
|
+
# depth_bins = np.arange(sgn*d, sgn*n, depth_interval)
|
153
|
+
depth_bins = np.linspace(sgn*d, sgn*n, bins)
|
55
154
|
f = sp.interpolate.interp1d(
|
56
155
|
depth_bins,
|
57
156
|
data[:, i],
|
@@ -61,9 +160,9 @@ def regrid2d(
|
|
61
160
|
)
|
62
161
|
gridz = f(z)
|
63
162
|
|
64
|
-
|
163
|
+
regridded_data[:, i] = gridz
|
65
164
|
|
66
|
-
return z,
|
165
|
+
return abs(z), regridded_data
|
67
166
|
|
68
167
|
|
69
168
|
def regrid3d(
|
@@ -71,24 +170,96 @@ def regrid3d(
|
|
71
170
|
vlobj,
|
72
171
|
data,
|
73
172
|
fill_value,
|
74
|
-
|
173
|
+
end_bin_option="cell",
|
75
174
|
trimends=None,
|
76
175
|
method="nearest",
|
176
|
+
orientation="up",
|
177
|
+
boundary_limit=0,
|
77
178
|
):
|
179
|
+
"""
|
180
|
+
Regrids 3D data onto a new grid based on specified parameters.
|
181
|
+
|
182
|
+
Parameters:
|
183
|
+
-----------
|
184
|
+
flobj : object
|
185
|
+
The fixed leader object that contains information
|
186
|
+
about the fixed leader data.
|
187
|
+
|
188
|
+
vlobj : object
|
189
|
+
The variable leader object that contains information
|
190
|
+
about the variable leader data.
|
191
|
+
|
192
|
+
data : array-like
|
193
|
+
The 3D data array to be regridded, with dimensions
|
194
|
+
typically representing time, depth, and another axis (e.g., ensembles).
|
195
|
+
|
196
|
+
fill_value : scalar
|
197
|
+
The value used to fill missing or undefined grid points.
|
198
|
+
|
199
|
+
end_bin_option : str or float, optional, default="cell"
|
200
|
+
The depth of the last bin or boundary for the grid.
|
201
|
+
Options include:
|
202
|
+
- "cell" : Calculates the depth of the default last bin for the grid.
|
203
|
+
Truncates to surface for upward ADCP.
|
204
|
+
- "surface" : The data is gridded till the surface.
|
205
|
+
- "manual" : User-defined depth for the grid.
|
206
|
+
Use boundary_limit option to provide the value.
|
207
|
+
Otherwise, a specific numerical depth value can be provided.
|
208
|
+
|
209
|
+
trimends : tuple of floats, optional, default=None
|
210
|
+
If provided, defines the ensemble range (start, end) for
|
211
|
+
calculating the maximum/minimum transducer depth.
|
212
|
+
Helps avoiding the deployment or retrieval data.
|
213
|
+
E.g., (10, 3000)
|
214
|
+
|
215
|
+
method : str, optional, default="nearest"
|
216
|
+
The interpolation method to use for regridding based
|
217
|
+
on scipy.interpolate.interp1d.
|
218
|
+
Options include:
|
219
|
+
- "nearest" : Nearest neighbor interpolation.
|
220
|
+
- "linear" : Linear interpolation.
|
221
|
+
- "cubic" : Cubic interpolation.
|
222
|
+
|
223
|
+
orientation : str, optional, default="up"
|
224
|
+
Defines the direction of the regridding for an upward/downward looking ADCP. Options include:
|
225
|
+
- "up" : Regrid upwards (for upward-looking ADCP).
|
226
|
+
- "down" : Regrid downwards (for downward-looking ADCP).
|
227
|
+
|
228
|
+
boundary_limit : float, optional, default=0
|
229
|
+
The limit for the boundary depth. This restricts the grid regridding to depths beyond the specified limit.
|
230
|
+
|
231
|
+
Returns:
|
232
|
+
--------
|
233
|
+
z : array-like
|
234
|
+
The regridded depth array.
|
235
|
+
regridded_data : array-like
|
236
|
+
The regridded 3D data array, based on the specified method,
|
237
|
+
orientation, and other parameters.
|
238
|
+
|
239
|
+
Notes:
|
240
|
+
------
|
241
|
+
- If `end_bin_option == boundary`, then `boundary_limit` is used to regrid the data.
|
242
|
+
- This function allows for flexible regridding of 3D data to fit a new grid, supporting different interpolation methods.
|
243
|
+
- The `boundary_limit` parameter helps restrict regridding to depths above or below a certain threshold.
|
244
|
+
- This function is an extension of 2D regridding to handle the time dimension or other additional axes in the data.
|
245
|
+
"""
|
246
|
+
|
78
247
|
beams = flobj.field()["Beams"]
|
79
248
|
z, data_dummy = regrid2d(
|
80
249
|
flobj,
|
81
250
|
vlobj,
|
82
251
|
data[0, :, :],
|
83
252
|
fill_value,
|
84
|
-
|
253
|
+
end_bin_option=end_bin_option,
|
85
254
|
trimends=trimends,
|
86
255
|
method=method,
|
256
|
+
orientation=orientation,
|
257
|
+
boundary_limit=boundary_limit,
|
87
258
|
)
|
88
259
|
|
89
260
|
newshape = np.shape(data_dummy)
|
90
|
-
|
91
|
-
|
261
|
+
regridded_data = np.zeros((beams, newshape[0], newshape[1]))
|
262
|
+
regridded_data[0, :, :] = data_dummy
|
92
263
|
|
93
264
|
for i in range(beams - 1):
|
94
265
|
z, data_dummy = regrid2d(
|
@@ -96,27 +267,13 @@ def regrid3d(
|
|
96
267
|
vlobj,
|
97
268
|
data[i + 1, :, :],
|
98
269
|
fill_value,
|
99
|
-
|
270
|
+
end_bin_option=end_bin_option,
|
100
271
|
trimends=trimends,
|
101
272
|
method=method,
|
273
|
+
orientation=orientation,
|
274
|
+
boundary_limit=boundary_limit,
|
102
275
|
)
|
103
|
-
|
104
|
-
|
105
|
-
return z,
|
106
|
-
|
107
|
-
|
108
|
-
# # read data
|
109
|
-
# filename = "BGS11000.000"
|
110
|
-
# fl = rd.FixedLeader(filename, run="fortran")
|
111
|
-
# vl = rd.VariableLeader(filename, run="fortran")
|
112
|
-
# # echo = rd.echo(filename, run="fortran")
|
113
|
-
# vel = rd.velocity(filename, run="fortran")
|
114
|
-
# pressure = vl.vleader["Pressure"]
|
115
|
-
#
|
116
|
-
# shape = np.shape(vel[0, :, :])
|
117
|
-
# mask = np.zeros(shape)
|
118
|
-
# orig_mask = np.copy(mask)
|
119
|
-
#
|
120
|
-
# z, newvel = regrid2d(fl, vl, vel[0, :, :], fill_value=-32768)
|
121
|
-
# z, newmask = regrid(mask[:, :], pressure, depth_interval=4, fill_value=1)
|
122
|
-
# z, newvel3d = regrid3d(vel, pressure, depth_interval=4, fill_value=-32768)
|
276
|
+
regridded_data[i + 1, :, :] = data_dummy
|
277
|
+
|
278
|
+
return z, regridded_data
|
279
|
+
|
pyadps/utils/velocity_test.py
CHANGED
@@ -1,39 +1,74 @@
|
|
1
1
|
from itertools import groupby
|
2
2
|
|
3
|
+
import requests
|
3
4
|
import numpy as np
|
4
5
|
import scipy as sp
|
5
|
-
import wmm2020
|
6
6
|
|
7
|
+
def wmm2020api(lat1, lon1, year):
|
8
|
+
"""
|
9
|
+
This function uses the WMM2020 API to retrieve the magnetic field values at a given location
|
10
|
+
The API need latitude, longitude and year to perform the calculation. The key in the function
|
11
|
+
must be updated time to time since the API is subjected to timely updates and the key may change.
|
12
|
+
|
13
|
+
Args:
|
14
|
+
Latitude (float)
|
15
|
+
Longitude (float)
|
16
|
+
startYear (int)
|
7
17
|
|
8
|
-
|
18
|
+
Returns:
|
19
|
+
mag -> magnetic declination at the given location in degree.
|
9
20
|
"""
|
10
|
-
|
11
|
-
|
21
|
+
baseurl = "https://www.ngdc.noaa.gov/geomag-web/calculators/calculateDeclination?"
|
22
|
+
key = "zNEw7"
|
23
|
+
resultFormat="json"
|
24
|
+
url = "{}lat1={}&lon1={}&key={}&startYear{}&resultFormat={}".format(baseurl, lat1, lon1, key, year, resultFormat)
|
25
|
+
response = requests.get(url)
|
26
|
+
data = response.json()
|
27
|
+
results = data["result"][0]
|
28
|
+
mag = [[results["declination"]]]
|
29
|
+
|
30
|
+
return mag
|
31
|
+
|
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
|
+
|
12
37
|
|
13
38
|
Args:
|
14
|
-
velocity (numpy array): velocity(beam, depth, time)
|
15
39
|
lat (parameter, float): Latitude in decimals
|
16
40
|
lon (parameter, float): Longitude in decimals
|
17
41
|
depth (parameter, float): depth in m
|
18
42
|
year (parameter, integer): Year
|
19
43
|
|
20
44
|
Returns:
|
21
|
-
velocity (numpy array): Rotated velocity using magnetic declination
|
22
45
|
mag: Magnetic declination (degrees)
|
23
46
|
"""
|
47
|
+
import wmm2020
|
24
48
|
mag = wmm2020.wmm(lat, lon, depth, year)
|
25
|
-
mag =
|
49
|
+
mag = mag.decl.data
|
50
|
+
|
51
|
+
return mag
|
52
|
+
|
53
|
+
def velocity_modifier(velocity, mag):
|
54
|
+
"""
|
55
|
+
The function uses magnetic declination from wmm2020 to correct
|
56
|
+
the horizontal velocities
|
57
|
+
|
58
|
+
Args:
|
59
|
+
velocity (numpy array): velocity array
|
60
|
+
mag: magnetic declination (degrees)
|
61
|
+
|
62
|
+
Returns:
|
63
|
+
velocity (numpy array): Rotated velocity using magnetic declination
|
64
|
+
"""
|
65
|
+
mag = np.deg2rad(mag[0][0])
|
26
66
|
velocity = np.where(velocity == -32768, np.nan, velocity)
|
27
|
-
velocity[0, :, :] = velocity[0, :, :] * np.cos(mag) + velocity[1, :, :] * np.sin(
|
28
|
-
|
29
|
-
)
|
30
|
-
velocity[1, :, :] = -1 * velocity[0, :, :] * np.sin(mag) + velocity[
|
31
|
-
1, :, :
|
32
|
-
] * np.cos(mag)
|
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)
|
33
69
|
velocity = np.where(velocity == np.nan, -32768, velocity)
|
34
70
|
|
35
|
-
return velocity
|
36
|
-
|
71
|
+
return velocity
|
37
72
|
|
38
73
|
def velocity_cutoff(velocity, mask, cutoff=250):
|
39
74
|
"""
|