pyTMD 2.2.4__tar.gz → 2.2.6__tar.gz
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.
- {pytmd-2.2.4 → pytmd-2.2.6}/.gitignore +2 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/CITATION.cff +2 -2
- {pytmd-2.2.4 → pytmd-2.2.6}/PKG-INFO +1 -1
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/astro.py +3 -3
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/compute.py +32 -16
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/compute_tide_corrections.py +1 -1
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/crs.py +1 -1
- pytmd-2.2.6/pyTMD/ellipse.py +196 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/io/GOT.py +8 -8
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/io/OTIS.py +58 -15
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/io/model.py +113 -40
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/predict.py +20 -12
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/solve/constants.py +38 -10
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/utilities.py +2 -598
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD.egg-info/PKG-INFO +1 -1
- {pytmd-2.2.4 → pytmd-2.2.6}/scripts/aviso_fes_tides.py +16 -4
- {pytmd-2.2.4 → pytmd-2.2.6}/scripts/gsfc_got_tides.py +6 -6
- pytmd-2.2.6/version.txt +1 -0
- pytmd-2.2.4/pyTMD/ellipse.py +0 -143
- pytmd-2.2.4/version.txt +0 -1
- {pytmd-2.2.4 → pytmd-2.2.6}/CODE_OF_CONDUCT.rst +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/CONTRIBUTORS.rst +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/LICENSE +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/MANIFEST.in +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/README.rst +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/providers/AVISO.json +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/providers/ESR.json +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/providers/GSFC.json +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/providers/README.rst +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/providers/TPXO.json +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/providers/_model_to_database.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/providers/_providers_to_database.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/providers/_update_providers.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/providers/providers.json +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/__init__.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/arguments.py +2 -2
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/data/ce1973_tab1.txt +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/data/ct1971_tab5.txt +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/data/d1921_tab.txt +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/data/database.json +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/data/doodson.json +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/data/opoleloadcoefcmcor.txt.gz +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/data/tab5.2e.txt +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/data/tab5.3a.txt +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/data/tab5.3b.txt +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/interpolate.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/io/ATLAS.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/io/FES.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/io/IERS.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/io/__init__.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/io/constituents.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/math.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/solve/__init__.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/spatial.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/tools.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD/version.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD.egg-info/SOURCES.txt +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD.egg-info/dependency_links.txt +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD.egg-info/requires.txt +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyTMD.egg-info/top_level.txt +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/pyproject.toml +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/scripts/arcticdata_tides.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/scripts/reduce_OTIS_files.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/scripts/verify_box_tpxo.py +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/setup.cfg +0 -0
- {pytmd-2.2.4 → pytmd-2.2.6}/setup.py +0 -0
|
@@ -36,8 +36,8 @@ url: 'https://pytmd.readthedocs.io'
|
|
|
36
36
|
repository: 'https://pypi.org/project/pyTMD'
|
|
37
37
|
repository-artifact: 'https://anaconda.org/conda-forge/pytmd'
|
|
38
38
|
doi: "10.5281/zenodo.5555395"
|
|
39
|
-
version: "2.2.
|
|
40
|
-
date-released: "2025-
|
|
39
|
+
version: "2.2.6"
|
|
40
|
+
date-released: "2025-07-24"
|
|
41
41
|
keywords:
|
|
42
42
|
- Ocean Tides
|
|
43
43
|
- Load Tides
|
|
@@ -49,7 +49,7 @@ UPDATE HISTORY:
|
|
|
49
49
|
Updated 08/2020: change time variable names to not overwrite functions
|
|
50
50
|
Updated 07/2020: added function docstrings
|
|
51
51
|
Updated 07/2018: added option ASTRO5 to use coefficients from Richard Ray
|
|
52
|
-
for use with the
|
|
52
|
+
for use with the Goddard Ocean Tides (GOT) model
|
|
53
53
|
added longitude of solar perigee (Ps) as an additional output
|
|
54
54
|
Updated 09/2017: added option MEEUS to use additional coefficients
|
|
55
55
|
from Meeus Astronomical Algorithms to calculate mean longitudes
|
|
@@ -503,7 +503,7 @@ def mean_obliquity(MJD: np.ndarray):
|
|
|
503
503
|
return atr*polynomial_sum(epsilon0, T)
|
|
504
504
|
|
|
505
505
|
def equation_of_time(MJD: np.ndarray):
|
|
506
|
-
"""Approximate
|
|
506
|
+
"""Approximate calculation of the difference between apparent and
|
|
507
507
|
mean solar times :cite:p:`Meeus:1991vh,Urban:2013vl`
|
|
508
508
|
|
|
509
509
|
Parameters
|
|
@@ -975,7 +975,7 @@ def _icrs_rotation_matrix(
|
|
|
975
975
|
include_polar_motion: bool = True
|
|
976
976
|
):
|
|
977
977
|
"""
|
|
978
|
-
Rotation matrix for
|
|
978
|
+
Rotation matrix for transforming from the
|
|
979
979
|
International Celestial Reference System (ICRS)
|
|
980
980
|
to the International Terrestrial Reference System (ITRS)
|
|
981
981
|
:cite:p:`Capitaine:2003fx,Capitaine:2003fw,Petit:2010tp`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
u"""
|
|
3
3
|
compute.py
|
|
4
|
-
Written by Tyler Sutterley (
|
|
4
|
+
Written by Tyler Sutterley (07/2025)
|
|
5
5
|
Calculates tidal elevations for correcting elevation or imagery data
|
|
6
6
|
Calculates tidal currents at locations and times
|
|
7
7
|
|
|
@@ -62,6 +62,8 @@ PROGRAM DEPENDENCIES:
|
|
|
62
62
|
interpolate.py: interpolation routines for spatial data
|
|
63
63
|
|
|
64
64
|
UPDATE HISTORY:
|
|
65
|
+
Updated 07/2025: mask mean pole values prior to valid epoch of convention
|
|
66
|
+
Updated 05/2025: added option to select constituents to read from model
|
|
65
67
|
Updated 12/2024: moved check points function as compute.tide_masks
|
|
66
68
|
Updated 11/2024: expose buffer distance for cropping tide model data
|
|
67
69
|
Updated 10/2024: compute delta times based on corrections type
|
|
@@ -89,7 +91,7 @@ UPDATE HISTORY:
|
|
|
89
91
|
Updated 06/2024: use np.clongdouble instead of np.longcomplex
|
|
90
92
|
Updated 04/2024: use wrapper to importlib for optional dependencies
|
|
91
93
|
Updated 02/2024: changed class name for ellipsoid parameters to datum
|
|
92
|
-
Updated 01/2024: made the
|
|
94
|
+
Updated 01/2024: made the inference of minor constituents an option
|
|
93
95
|
refactored lunisolar ephemerides functions
|
|
94
96
|
renamed module to compute and added tidal currents function
|
|
95
97
|
Updated 12/2023: use new crs class for coordinate reprojection
|
|
@@ -230,6 +232,7 @@ def tide_elevations(
|
|
|
230
232
|
EXTRAPOLATE: bool = False,
|
|
231
233
|
CUTOFF: int | float = 10.0,
|
|
232
234
|
CORRECTIONS: str | None = None,
|
|
235
|
+
CONSTITUENTS: list | None = None,
|
|
233
236
|
INFER_MINOR: bool = True,
|
|
234
237
|
MINOR_CONSTITUENTS: list | None = None,
|
|
235
238
|
APPEND_NODE: bool = False,
|
|
@@ -297,6 +300,8 @@ def tide_elevations(
|
|
|
297
300
|
Set to ``np.inf`` to extrapolate for all points
|
|
298
301
|
CORRECTIONS: str or None, default None
|
|
299
302
|
Nodal correction type, default based on model
|
|
303
|
+
CONSTITUENTS: list or None, default None
|
|
304
|
+
Specify constituents to read from model
|
|
300
305
|
INFER_MINOR: bool, default True
|
|
301
306
|
Infer the height values for minor tidal constituents
|
|
302
307
|
MINOR_CONSTITUENTS: list or None, default None
|
|
@@ -366,7 +371,8 @@ def tide_elevations(
|
|
|
366
371
|
nt = len(ts)
|
|
367
372
|
|
|
368
373
|
# read tidal constants and interpolate to grid points
|
|
369
|
-
amp, ph, c = model.extract_constants(lon, lat,
|
|
374
|
+
amp, ph, c = model.extract_constants(lon, lat,
|
|
375
|
+
type=model.type, constituents=CONSTITUENTS,
|
|
370
376
|
crop=CROP, bounds=BOUNDS, buffer=BUFFER, method=METHOD,
|
|
371
377
|
extrapolate=EXTRAPOLATE, cutoff=CUTOFF,
|
|
372
378
|
append_node=APPEND_NODE, apply_flexure=APPLY_FLEXURE)
|
|
@@ -395,7 +401,7 @@ def tide_elevations(
|
|
|
395
401
|
for i in range(nt):
|
|
396
402
|
TIDE = pyTMD.predict.map(ts.tide[i], hc, c,
|
|
397
403
|
deltat=deltat[i], corrections=nodal_corrections)
|
|
398
|
-
# calculate values for minor constituents by
|
|
404
|
+
# calculate values for minor constituents by inference
|
|
399
405
|
if INFER_MINOR:
|
|
400
406
|
MINOR = pyTMD.predict.infer_minor(ts.tide[i], hc, c,
|
|
401
407
|
deltat=deltat[i], corrections=nodal_corrections,
|
|
@@ -410,7 +416,7 @@ def tide_elevations(
|
|
|
410
416
|
tide.mask = np.any(hc.mask,axis=1)
|
|
411
417
|
tide.data[:] = pyTMD.predict.drift(ts.tide, hc, c,
|
|
412
418
|
deltat=deltat, corrections=nodal_corrections)
|
|
413
|
-
# calculate values for minor constituents by
|
|
419
|
+
# calculate values for minor constituents by inference
|
|
414
420
|
if INFER_MINOR:
|
|
415
421
|
minor = pyTMD.predict.infer_minor(ts.tide, hc, c,
|
|
416
422
|
deltat=deltat, corrections=nodal_corrections,
|
|
@@ -424,7 +430,7 @@ def tide_elevations(
|
|
|
424
430
|
HC = hc[s,None,:]
|
|
425
431
|
TIDE = pyTMD.predict.time_series(ts.tide, HC, c,
|
|
426
432
|
deltat=deltat, corrections=nodal_corrections)
|
|
427
|
-
# calculate values for minor constituents by
|
|
433
|
+
# calculate values for minor constituents by inference
|
|
428
434
|
if INFER_MINOR:
|
|
429
435
|
MINOR = pyTMD.predict.infer_minor(ts.tide, HC, c,
|
|
430
436
|
deltat=deltat, corrections=nodal_corrections,
|
|
@@ -458,6 +464,7 @@ def tide_currents(
|
|
|
458
464
|
EXTRAPOLATE: bool = False,
|
|
459
465
|
CUTOFF: int | float = 10.0,
|
|
460
466
|
CORRECTIONS: str | None = None,
|
|
467
|
+
CONSTITUENTS: list | None = None,
|
|
461
468
|
INFER_MINOR: bool = True,
|
|
462
469
|
MINOR_CONSTITUENTS: list | None = None,
|
|
463
470
|
FILL_VALUE: float = np.nan,
|
|
@@ -523,6 +530,8 @@ def tide_currents(
|
|
|
523
530
|
Set to ``np.inf`` to extrapolate for all points
|
|
524
531
|
CORRECTIONS: str or None, default None
|
|
525
532
|
Nodal correction type, default based on model
|
|
533
|
+
CONSTITUENTS: list or None, default None
|
|
534
|
+
Specify constituents to read from model
|
|
526
535
|
INFER_MINOR: bool, default True
|
|
527
536
|
Infer the height values for minor tidal constituents
|
|
528
537
|
MINOR_CONSTITUENTS: list or None, default None
|
|
@@ -595,7 +604,8 @@ def tide_currents(
|
|
|
595
604
|
# iterate over u and v currents
|
|
596
605
|
for t in model.type:
|
|
597
606
|
# read tidal constants and interpolate to grid points
|
|
598
|
-
amp, ph, c = model.extract_constants(lon, lat,
|
|
607
|
+
amp, ph, c = model.extract_constants(lon, lat,
|
|
608
|
+
type=t, constituents=CONSTITUENTS,
|
|
599
609
|
crop=CROP, bounds=BOUNDS, buffer=BUFFER, method=METHOD,
|
|
600
610
|
extrapolate=EXTRAPOLATE, cutoff=CUTOFF)
|
|
601
611
|
# calculate complex phase in radians for Euler's
|
|
@@ -623,7 +633,7 @@ def tide_currents(
|
|
|
623
633
|
for i in range(nt):
|
|
624
634
|
TIDE = pyTMD.predict.map(ts.tide[i], hc, c,
|
|
625
635
|
deltat=deltat[i], corrections=nodal_corrections)
|
|
626
|
-
# calculate values for minor constituents by
|
|
636
|
+
# calculate values for minor constituents by inference
|
|
627
637
|
if INFER_MINOR:
|
|
628
638
|
MINOR = pyTMD.predict.infer_minor(ts.tide[i], hc, c,
|
|
629
639
|
deltat=deltat[i], corrections=nodal_corrections,
|
|
@@ -638,7 +648,7 @@ def tide_currents(
|
|
|
638
648
|
tide[t].mask = np.any(hc.mask,axis=1)
|
|
639
649
|
tide[t].data[:] = pyTMD.predict.drift(ts.tide, hc, c,
|
|
640
650
|
deltat=deltat, corrections=nodal_corrections)
|
|
641
|
-
# calculate values for minor constituents by
|
|
651
|
+
# calculate values for minor constituents by inference
|
|
642
652
|
if INFER_MINOR:
|
|
643
653
|
minor = pyTMD.predict.infer_minor(ts.tide, hc, c,
|
|
644
654
|
deltat=deltat, corrections=nodal_corrections,
|
|
@@ -652,7 +662,7 @@ def tide_currents(
|
|
|
652
662
|
HC = hc[s,None,:]
|
|
653
663
|
TIDE = pyTMD.predict.time_series(ts.tide, HC, c,
|
|
654
664
|
deltat=deltat, corrections=nodal_corrections)
|
|
655
|
-
# calculate values for minor constituents by
|
|
665
|
+
# calculate values for minor constituents by inference
|
|
656
666
|
if INFER_MINOR:
|
|
657
667
|
MINOR = pyTMD.predict.infer_minor(ts.tide, HC, c,
|
|
658
668
|
deltat=deltat, corrections=nodal_corrections,
|
|
@@ -1055,9 +1065,10 @@ def LPT_displacements(
|
|
|
1055
1065
|
)
|
|
1056
1066
|
# calculate components of load pole tides
|
|
1057
1067
|
S = np.einsum('ti...,tji...->tj...', dxi, R)
|
|
1068
|
+
smask = np.reshape(np.any(dxi.mask, axis=1), (ny,nx))
|
|
1058
1069
|
# reshape to output dimensions
|
|
1059
1070
|
Srad.data[:,:,i] = np.reshape(S[:,2], (ny,nx))
|
|
1060
|
-
Srad.mask[:,:,i] = np.isnan(Srad.data[:,:,i])
|
|
1071
|
+
Srad.mask[:,:,i] = np.isnan(Srad.data[:,:,i]) | smask
|
|
1061
1072
|
elif (TYPE == 'drift'):
|
|
1062
1073
|
# calculate load pole tides in cartesian coordinates
|
|
1063
1074
|
XYZ = np.c_[X, Y, Z]
|
|
@@ -1071,10 +1082,11 @@ def LPT_displacements(
|
|
|
1071
1082
|
)
|
|
1072
1083
|
# calculate components of load pole tides
|
|
1073
1084
|
S = np.einsum('ti...,tji...->tj...', dxi, R)
|
|
1085
|
+
smask = np.any(dxi.mask, axis=1)
|
|
1074
1086
|
# reshape to output dimensions
|
|
1075
1087
|
Srad = np.ma.zeros((nt), fill_value=FILL_VALUE)
|
|
1076
1088
|
Srad.data[:] = S[:,2].copy()
|
|
1077
|
-
Srad.mask = np.isnan(Srad.data)
|
|
1089
|
+
Srad.mask = np.isnan(Srad.data) | smask
|
|
1078
1090
|
elif (TYPE == 'time series'):
|
|
1079
1091
|
nstation = len(x)
|
|
1080
1092
|
Srad = np.ma.zeros((nstation,nt), fill_value=FILL_VALUE)
|
|
@@ -1093,9 +1105,10 @@ def LPT_displacements(
|
|
|
1093
1105
|
)
|
|
1094
1106
|
# calculate components of load pole tides
|
|
1095
1107
|
S = np.einsum('ti...,ji...->tj...', dxi, R[s,:,:])
|
|
1108
|
+
smask = np.any(dxi.mask, axis=1)
|
|
1096
1109
|
# reshape to output dimensions
|
|
1097
1110
|
Srad.data[s,:] = S[:,2].copy()
|
|
1098
|
-
Srad.mask[s,:] = np.isnan(Srad.data[s,:])
|
|
1111
|
+
Srad.mask[s,:] = np.isnan(Srad.data[s,:]) | smask
|
|
1099
1112
|
|
|
1100
1113
|
# replace invalid data with fill values
|
|
1101
1114
|
Srad.data[Srad.mask] = Srad.fill_value
|
|
@@ -1279,9 +1292,10 @@ def OPT_displacements(
|
|
|
1279
1292
|
)
|
|
1280
1293
|
# calculate components of ocean pole tides
|
|
1281
1294
|
U = np.einsum('ti...,tji...->tj...', dxi, Rinv)
|
|
1295
|
+
umask = np.reshape(np.any(dxi.mask, axis=1), (ny,nx))
|
|
1282
1296
|
# reshape to output dimensions
|
|
1283
1297
|
Urad.data[:,:,i] = np.reshape(U[:,2], (ny,nx))
|
|
1284
|
-
Urad.mask[:,:,i] = np.isnan(Urad.data[:,:,i])
|
|
1298
|
+
Urad.mask[:,:,i] = np.isnan(Urad.data[:,:,i]) | umask
|
|
1285
1299
|
elif (TYPE == 'drift'):
|
|
1286
1300
|
# calculate ocean pole tides in cartesian coordinates
|
|
1287
1301
|
XYZ = np.c_[X, Y, Z]
|
|
@@ -1297,10 +1311,11 @@ def OPT_displacements(
|
|
|
1297
1311
|
)
|
|
1298
1312
|
# calculate components of ocean pole tides
|
|
1299
1313
|
U = np.einsum('ti...,tji...->tj...', dxi, Rinv)
|
|
1314
|
+
umask = np.any(dxi.mask, axis=1)
|
|
1300
1315
|
# convert to masked array
|
|
1301
1316
|
Urad = np.ma.zeros((nt), fill_value=FILL_VALUE)
|
|
1302
1317
|
Urad.data[:] = U[:,2].copy()
|
|
1303
|
-
Urad.mask = np.isnan(Urad.data)
|
|
1318
|
+
Urad.mask = np.isnan(Urad.data) | umask
|
|
1304
1319
|
elif (TYPE == 'time series'):
|
|
1305
1320
|
nstation = len(x)
|
|
1306
1321
|
Urad = np.ma.zeros((nstation,nt), fill_value=FILL_VALUE)
|
|
@@ -1322,9 +1337,10 @@ def OPT_displacements(
|
|
|
1322
1337
|
)
|
|
1323
1338
|
# calculate components of ocean pole tides
|
|
1324
1339
|
U = np.einsum('ti...,ji...->tj...', dxi, Rinv[s,:,:])
|
|
1340
|
+
umask = np.any(dxi.mask, axis=1)
|
|
1325
1341
|
# reshape to output dimensions
|
|
1326
1342
|
Urad.data[s,:] = U[:,2].copy()
|
|
1327
|
-
Urad.mask[s,:] = np.isnan(Urad.data[s,:])
|
|
1343
|
+
Urad.mask[s,:] = np.isnan(Urad.data[s,:]) | umask
|
|
1328
1344
|
|
|
1329
1345
|
# replace invalid data with fill values
|
|
1330
1346
|
Urad.data[Urad.mask] = Urad.fill_value
|
|
@@ -59,7 +59,7 @@ PROGRAM DEPENDENCIES:
|
|
|
59
59
|
interpolate.py: interpolation routines for spatial data
|
|
60
60
|
|
|
61
61
|
UPDATE HISTORY:
|
|
62
|
-
Updated 01/2024: made the
|
|
62
|
+
Updated 01/2024: made the inference of minor constituents an option
|
|
63
63
|
refactored lunisolar ephemerides functions
|
|
64
64
|
deprecated in favor of refactored compute.py module
|
|
65
65
|
Updated 12/2023: use new crs class for coordinate reprojection
|
|
@@ -189,7 +189,7 @@ class crs:
|
|
|
189
189
|
PROJECTION: int, str or dict
|
|
190
190
|
Coordinate Reference System
|
|
191
191
|
"""
|
|
192
|
-
# coordinate reference system
|
|
192
|
+
# coordinate reference system dictionary
|
|
193
193
|
try:
|
|
194
194
|
CRS = pyproj.CRS.from_user_input(PROJECTION)
|
|
195
195
|
except (ValueError, pyproj.exceptions.CRSError):
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
u"""
|
|
3
|
+
ellipse.py
|
|
4
|
+
Written by Tyler Sutterley (05/2025)
|
|
5
|
+
Expresses the amplitudes and phases for the u and v components in terms of
|
|
6
|
+
four ellipse parameters using Foreman's formula
|
|
7
|
+
|
|
8
|
+
CALLING SEQUENCE:
|
|
9
|
+
umajor,uminor,uincl,uphase = pyTMD.ellipse.ellipse(u,v)
|
|
10
|
+
|
|
11
|
+
INPUTS:
|
|
12
|
+
u: zonal current (EW)
|
|
13
|
+
v: meridional current (NS)
|
|
14
|
+
|
|
15
|
+
OUTPUTS:
|
|
16
|
+
major: amplitude of the semimajor semi-axis
|
|
17
|
+
minor: amplitude of the semiminor semi-axis
|
|
18
|
+
incl: angle of inclination of the northern semimajor semi-axis
|
|
19
|
+
phase: phase lag of the maximum current behind the maximum tidal potential
|
|
20
|
+
of the individual constituent
|
|
21
|
+
|
|
22
|
+
REFERENCE:
|
|
23
|
+
M. G. G. Foreman and R. F. Henry, "The harmonic analysis of tidal model time
|
|
24
|
+
series", Advances in Water Resources, 12(3), 109-120, (1989).
|
|
25
|
+
https://doi.org/10.1016/0309-1708(89)90017-1
|
|
26
|
+
|
|
27
|
+
UPDATE HISTORY:
|
|
28
|
+
Updated 06/2025: added function to calculate x and y coordinates of ellipse
|
|
29
|
+
Updated 01/2024: added inverse function to get currents from parameters
|
|
30
|
+
use complex algebra to calculate tidal ellipse parameters
|
|
31
|
+
Updated 09/2023: renamed to ellipse.py (from tidal_ellipse.py)
|
|
32
|
+
Updated 03/2023: add basic variable typing to function inputs
|
|
33
|
+
Updated 04/2022: updated docstrings to numpy documentation format
|
|
34
|
+
Written 07/2020
|
|
35
|
+
"""
|
|
36
|
+
from __future__ import annotations
|
|
37
|
+
|
|
38
|
+
import numpy as np
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"ellipse",
|
|
42
|
+
"inverse",
|
|
43
|
+
"_xy"
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
def ellipse(u: np.ndarray, v: np.ndarray):
|
|
47
|
+
"""
|
|
48
|
+
Expresses the amplitudes and phases for the u and v components in terms of
|
|
49
|
+
four ellipse parameters using Foreman's formula :cite:p:`Foreman:1989dt`
|
|
50
|
+
|
|
51
|
+
Parameters
|
|
52
|
+
----------
|
|
53
|
+
u: np.ndarray
|
|
54
|
+
zonal current (EW)
|
|
55
|
+
v: np.ndarray
|
|
56
|
+
meridional current (NS)
|
|
57
|
+
|
|
58
|
+
Returns
|
|
59
|
+
-------
|
|
60
|
+
major: np.ndarray
|
|
61
|
+
amplitude of the semi-major axis
|
|
62
|
+
minor: np.ndarray
|
|
63
|
+
amplitude of the semi-minor axis
|
|
64
|
+
incl: np.ndarray
|
|
65
|
+
angle of inclination of the northern semi-major axis
|
|
66
|
+
phase: np.ndarray
|
|
67
|
+
phase lag of the maximum current behind the maximum tidal potential
|
|
68
|
+
"""
|
|
69
|
+
# validate inputs
|
|
70
|
+
u = np.atleast_1d(u)
|
|
71
|
+
v = np.atleast_1d(v)
|
|
72
|
+
# wp, wm: complex radius of positively and negatively rotating vectors
|
|
73
|
+
wp = (u + 1j*v)/2.0
|
|
74
|
+
wm = np.conj(u - 1j*v)/2.0
|
|
75
|
+
# ap, am: amplitudes of positively and negatively rotating vectors
|
|
76
|
+
ap = np.abs(wp)
|
|
77
|
+
am = np.abs(wm)
|
|
78
|
+
# ep, em: phases of positively and negatively rotating vectors
|
|
79
|
+
ep = np.angle(wp, deg=True)
|
|
80
|
+
em = np.angle(wm, deg=True)
|
|
81
|
+
# determine the amplitudes of the semimajor and semiminor axes
|
|
82
|
+
# using Foreman's formula
|
|
83
|
+
major = (ap + am)
|
|
84
|
+
minor = (ap - am)
|
|
85
|
+
# determine the inclination and phase using Foreman's formula
|
|
86
|
+
incl = (em + ep)/2.0
|
|
87
|
+
phase = (em - ep)/2.0
|
|
88
|
+
# adjust orientation of ellipse
|
|
89
|
+
k = (incl//180.0)
|
|
90
|
+
incl -= 180.0*k
|
|
91
|
+
phase += 180.0*k
|
|
92
|
+
phase = np.mod(phase, 360.0)
|
|
93
|
+
# return values
|
|
94
|
+
return (major, minor, incl, phase)
|
|
95
|
+
|
|
96
|
+
def inverse(
|
|
97
|
+
major: np.ndarray,
|
|
98
|
+
minor: np.ndarray,
|
|
99
|
+
incl: np.ndarray,
|
|
100
|
+
phase: np.ndarray
|
|
101
|
+
):
|
|
102
|
+
"""
|
|
103
|
+
Calculates currents u, v using the four tidal ellipse
|
|
104
|
+
parameters from Foreman's formula :cite:p:`Foreman:1989dt`
|
|
105
|
+
|
|
106
|
+
Parameters
|
|
107
|
+
----------
|
|
108
|
+
major: np.ndarray
|
|
109
|
+
amplitude of the semi-major axis
|
|
110
|
+
minor: np.ndarray
|
|
111
|
+
amplitude of the semi-minor axis
|
|
112
|
+
incl: np.ndarray
|
|
113
|
+
angle of inclination of the northern semi-major axis
|
|
114
|
+
phase: np.ndarray
|
|
115
|
+
phase lag of the maximum current behind the maximum tidal potential
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
u: np.ndarray
|
|
120
|
+
zonal current (EW)
|
|
121
|
+
v: np.ndarray
|
|
122
|
+
meridional current (NS)
|
|
123
|
+
"""
|
|
124
|
+
# validate inputs
|
|
125
|
+
major = np.atleast_1d(major)
|
|
126
|
+
minor = np.atleast_1d(minor)
|
|
127
|
+
# convert inclination and phase to radians
|
|
128
|
+
incl = np.atleast_1d(incl)*np.pi/180.0
|
|
129
|
+
phase = np.atleast_1d(phase)*np.pi/180.0
|
|
130
|
+
# ep, em: phases of positively and negatively rotating vectors
|
|
131
|
+
ep = (incl - phase)
|
|
132
|
+
em = (incl + phase)
|
|
133
|
+
# ap, am: amplitudes of positively and negatively rotating vectors
|
|
134
|
+
ap = (major + minor)/2.0
|
|
135
|
+
am = (major - minor)/2.0
|
|
136
|
+
# wp, wm: complex radius of positively and negatively rotating vectors
|
|
137
|
+
wp = ap * np.exp(1j*ep)
|
|
138
|
+
wm = am * np.exp(1j*em)
|
|
139
|
+
# calculate complex currents
|
|
140
|
+
u = wp + np.conj(wm)
|
|
141
|
+
v = -1j*(wp - np.conj(wm))
|
|
142
|
+
# return values
|
|
143
|
+
return (u, v)
|
|
144
|
+
|
|
145
|
+
def _xy(
|
|
146
|
+
major: float | np.ndarray,
|
|
147
|
+
minor: float | np.ndarray,
|
|
148
|
+
incl: float | np.ndarray,
|
|
149
|
+
**kwargs
|
|
150
|
+
):
|
|
151
|
+
"""
|
|
152
|
+
Calculates the x and y coordinates of the tidal ellipse
|
|
153
|
+
|
|
154
|
+
Parameters
|
|
155
|
+
----------
|
|
156
|
+
major: np.ndarray
|
|
157
|
+
amplitude of the semi-major axis
|
|
158
|
+
minor: np.ndarray
|
|
159
|
+
amplitude of the semi-minor axis
|
|
160
|
+
incl: np.ndarray
|
|
161
|
+
angle of inclination of the northern semi-major axis
|
|
162
|
+
phase: np.ndarray or None, default None
|
|
163
|
+
phase lag of the maximum current behind the maximum tidal potential
|
|
164
|
+
xy: tuple, default (0.0, 0.0)
|
|
165
|
+
center of the ellipse (x, y)
|
|
166
|
+
N: int or None, default None
|
|
167
|
+
number of points to calculate along the ellipse
|
|
168
|
+
|
|
169
|
+
Returns
|
|
170
|
+
-------
|
|
171
|
+
x: np.ndarray
|
|
172
|
+
x coordinates of the tidal ellipse
|
|
173
|
+
y: np.ndarray
|
|
174
|
+
y coordinates of the tidal ellipse
|
|
175
|
+
"""
|
|
176
|
+
# set default number of points
|
|
177
|
+
kwargs.setdefault('phase', None)
|
|
178
|
+
kwargs.setdefault('xy', (0.0, 0.0))
|
|
179
|
+
kwargs.setdefault('N', 1000)
|
|
180
|
+
# validate inputs
|
|
181
|
+
phi = incl*np.pi/180.0
|
|
182
|
+
# calculate the angle of the ellipse
|
|
183
|
+
if kwargs['phase'] is not None:
|
|
184
|
+
# use the phase lag and inclination
|
|
185
|
+
th = (kwargs['phase'] + incl)*np.pi/180.0
|
|
186
|
+
else:
|
|
187
|
+
# use a full rotation
|
|
188
|
+
th = np.linspace(0, 2*np.pi, kwargs['N'])
|
|
189
|
+
# calculate x and y coordinates
|
|
190
|
+
x = kwargs['xy'][0] + \
|
|
191
|
+
major*np.cos(th)*np.cos(phi) - \
|
|
192
|
+
minor*np.sin(th)*np.sin(phi)
|
|
193
|
+
y = kwargs['xy'][1] + \
|
|
194
|
+
major*np.cos(th)*np.sin(phi) + \
|
|
195
|
+
minor*np.sin(th)*np.cos(phi)
|
|
196
|
+
return (x, y)
|
|
@@ -3,10 +3,10 @@ u"""
|
|
|
3
3
|
GOT.py
|
|
4
4
|
Written by Tyler Sutterley (11/2024)
|
|
5
5
|
|
|
6
|
-
Reads files for Richard Ray's
|
|
7
|
-
calculations to run the tide program
|
|
8
|
-
Includes functions to extract tidal harmonic constants out of a tidal
|
|
9
|
-
given locations
|
|
6
|
+
Reads files for Richard Ray's Goddard Ocean Tide (GOT) models and makes
|
|
7
|
+
initial calculations to run the tide program
|
|
8
|
+
Includes functions to extract tidal harmonic constants out of a tidal
|
|
9
|
+
model for given locations
|
|
10
10
|
|
|
11
11
|
INPUTS:
|
|
12
12
|
ilon: longitude to interpolate
|
|
@@ -123,7 +123,7 @@ def extract_constants(
|
|
|
123
123
|
**kwargs
|
|
124
124
|
):
|
|
125
125
|
"""
|
|
126
|
-
Reads files for Richard Ray's
|
|
126
|
+
Reads files for Richard Ray's Goddard Ocean Tide (GOT) models
|
|
127
127
|
|
|
128
128
|
Makes initial calculations to run the tide program
|
|
129
129
|
|
|
@@ -315,7 +315,7 @@ def read_constants(
|
|
|
315
315
|
**kwargs
|
|
316
316
|
):
|
|
317
317
|
"""
|
|
318
|
-
Reads files for Richard Ray's
|
|
318
|
+
Reads files for Richard Ray's Goddard Ocean Tide (GOT) models
|
|
319
319
|
|
|
320
320
|
Parameters
|
|
321
321
|
----------
|
|
@@ -540,7 +540,7 @@ def read_ascii_file(
|
|
|
540
540
|
**kwargs
|
|
541
541
|
):
|
|
542
542
|
"""
|
|
543
|
-
Read Richard Ray's
|
|
543
|
+
Read Richard Ray's Goddard Ocean Tide (GOT) model file
|
|
544
544
|
|
|
545
545
|
Parameters
|
|
546
546
|
----------
|
|
@@ -625,7 +625,7 @@ def read_netcdf_file(
|
|
|
625
625
|
**kwargs
|
|
626
626
|
):
|
|
627
627
|
"""
|
|
628
|
-
Read Richard Ray's
|
|
628
|
+
Read Richard Ray's Goddard Ocean Tide (GOT) netCDF4 model file
|
|
629
629
|
|
|
630
630
|
Parameters
|
|
631
631
|
----------
|