pyTMD 2.2.1__tar.gz → 2.2.2__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.
Files changed (77) hide show
  1. {pytmd-2.2.1 → pytmd-2.2.2}/CITATION.cff +3 -3
  2. {pytmd-2.2.1 → pytmd-2.2.2}/PKG-INFO +13 -17
  3. {pytmd-2.2.1 → pytmd-2.2.2}/README.rst +10 -10
  4. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/__init__.py +1 -8
  5. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/arguments.py +13 -7
  6. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/astro.py +2 -2
  7. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/compute.py +5 -5
  8. pytmd-2.2.2/pyTMD/crs.py +247 -0
  9. pytmd-2.2.2/pyTMD/data/d1921_tab.txt +21 -0
  10. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/io/constituents.py +16 -12
  11. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/predict.py +16 -3
  12. pytmd-2.2.2/pyTMD/spatial.py +1419 -0
  13. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD.egg-info/PKG-INFO +13 -17
  14. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD.egg-info/SOURCES.txt +1 -9
  15. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD.egg-info/requires.txt +0 -4
  16. {pytmd-2.2.1 → pytmd-2.2.2}/pyproject.toml +3 -9
  17. pytmd-2.2.2/version.txt +1 -0
  18. pytmd-2.2.1/pyTMD/check_points.py +0 -119
  19. pytmd-2.2.1/pyTMD/crs.py +0 -629
  20. pytmd-2.2.1/pyTMD/eop.py +0 -240
  21. pytmd-2.2.1/pyTMD/spatial.py +0 -2275
  22. pytmd-2.2.1/pyTMD/time.py +0 -355
  23. pytmd-2.2.1/scripts/compute_LPET_elevations.py +0 -413
  24. pytmd-2.2.1/scripts/compute_LPT_displacements.py +0 -533
  25. pytmd-2.2.1/scripts/compute_OPT_displacements.py +0 -565
  26. pytmd-2.2.1/scripts/compute_SET_displacements.py +0 -511
  27. pytmd-2.2.1/scripts/compute_tidal_currents.py +0 -640
  28. pytmd-2.2.1/scripts/compute_tidal_elevations.py +0 -646
  29. pytmd-2.2.1/version.txt +0 -1
  30. {pytmd-2.2.1 → pytmd-2.2.2}/.gitignore +0 -0
  31. {pytmd-2.2.1 → pytmd-2.2.2}/CODE_OF_CONDUCT.rst +0 -0
  32. {pytmd-2.2.1 → pytmd-2.2.2}/CONTRIBUTORS.rst +0 -0
  33. {pytmd-2.2.1 → pytmd-2.2.2}/LICENSE +0 -0
  34. {pytmd-2.2.1 → pytmd-2.2.2}/MANIFEST.in +0 -0
  35. {pytmd-2.2.1 → pytmd-2.2.2}/providers/AVISO.json +0 -0
  36. {pytmd-2.2.1 → pytmd-2.2.2}/providers/ESR.json +0 -0
  37. {pytmd-2.2.1 → pytmd-2.2.2}/providers/GSFC.json +0 -0
  38. {pytmd-2.2.1 → pytmd-2.2.2}/providers/README.rst +0 -0
  39. {pytmd-2.2.1 → pytmd-2.2.2}/providers/TPXO.json +0 -0
  40. {pytmd-2.2.1 → pytmd-2.2.2}/providers/_model_to_database.py +0 -0
  41. {pytmd-2.2.1 → pytmd-2.2.2}/providers/_providers_to_database.py +0 -0
  42. {pytmd-2.2.1 → pytmd-2.2.2}/providers/_update_providers.py +0 -0
  43. {pytmd-2.2.1 → pytmd-2.2.2}/providers/providers.json +0 -0
  44. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/compute_tide_corrections.py +0 -0
  45. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/data/ce1973_tab1.txt +0 -0
  46. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/data/ct1971_tab5.txt +0 -0
  47. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/data/database.json +0 -0
  48. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/data/doodson.json +0 -0
  49. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/data/opoleloadcoefcmcor.txt.gz +0 -0
  50. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/data/tab5.2e.txt +0 -0
  51. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/data/tab5.3a.txt +0 -0
  52. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/data/tab5.3b.txt +0 -0
  53. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/ellipse.py +0 -0
  54. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/interpolate.py +0 -0
  55. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/io/ATLAS.py +0 -0
  56. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/io/FES.py +0 -0
  57. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/io/GOT.py +0 -0
  58. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/io/IERS.py +0 -0
  59. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/io/OTIS.py +0 -0
  60. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/io/__init__.py +0 -0
  61. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/io/model.py +0 -0
  62. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/math.py +0 -0
  63. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/solve/__init__.py +0 -0
  64. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/solve/constants.py +0 -0
  65. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/tools.py +0 -0
  66. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/utilities.py +0 -0
  67. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD/version.py +0 -0
  68. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD.egg-info/dependency_links.txt +0 -0
  69. {pytmd-2.2.1 → pytmd-2.2.2}/pyTMD.egg-info/top_level.txt +0 -0
  70. {pytmd-2.2.1 → pytmd-2.2.2}/scripts/arcticdata_tides.py +0 -0
  71. {pytmd-2.2.1 → pytmd-2.2.2}/scripts/aviso_fes_tides.py +0 -0
  72. {pytmd-2.2.1 → pytmd-2.2.2}/scripts/gsfc_got_tides.py +0 -0
  73. {pytmd-2.2.1 → pytmd-2.2.2}/scripts/reduce_OTIS_files.py +0 -0
  74. {pytmd-2.2.1 → pytmd-2.2.2}/scripts/usap_cats_tides.py +0 -0
  75. {pytmd-2.2.1 → pytmd-2.2.2}/scripts/verify_box_tpxo.py +0 -0
  76. {pytmd-2.2.1 → pytmd-2.2.2}/setup.cfg +0 -0
  77. {pytmd-2.2.1 → pytmd-2.2.2}/setup.py +0 -0
@@ -31,13 +31,13 @@ identifiers:
31
31
  - type: doi
32
32
  value: 10.5281/zenodo.5555395
33
33
  description: Zenodo Archive
34
- repository-code: 'https://github.com/tsutterley/pyTMD'
34
+ repository-code: 'https://github.com/pyTMD/pyTMD'
35
35
  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.1"
40
- date-released: "2025-02-10"
39
+ version: "2.2.2"
40
+ date-released: "2025-02-19"
41
41
  keywords:
42
42
  - Ocean Tides
43
43
  - Load Tides
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pyTMD
3
- Version: 2.2.1
3
+ Version: 2.2.2
4
4
  Summary: Python-based tidal prediction software for estimating ocean, load, solid Earth and pole tides
5
5
  Author: Tyler Sutterley
6
6
  Author-email: tsutterl@uw.edu
@@ -29,8 +29,8 @@ License: MIT License
29
29
 
30
30
  Project-URL: Homepage, https://pytmd.readthedocs.io
31
31
  Project-URL: Documentation, https://pytmd.readthedocs.io
32
- Project-URL: Repository, https://github.com/tsutterley/pyTMD
33
- Project-URL: Issues, https://github.com/tsutterley/pyTMD/issues
32
+ Project-URL: Repository, https://github.com/pyTMD/pyTMD
33
+ Project-URL: Issues, https://github.com/pyTMD/pyTMD/issues
34
34
  Keywords: Ocean Tides,Load Tides,Pole Tides,Solid Earth Tides,Tidal Prediction
35
35
  Classifier: Development Status :: 3 - Alpha
36
36
  Classifier: Intended Audience :: Science/Research
@@ -70,16 +70,12 @@ Requires-Dist: sphinx-design; extra == "doc"
70
70
  Requires-Dist: sphinx_rtd_theme; extra == "doc"
71
71
  Provides-Extra: all
72
72
  Requires-Dist: cartopy; extra == "all"
73
- Requires-Dist: gdal; extra == "all"
74
- Requires-Dist: h5py; extra == "all"
75
73
  Requires-Dist: ipyleaflet; extra == "all"
76
74
  Requires-Dist: ipywidgets; extra == "all"
77
75
  Requires-Dist: jplephem; extra == "all"
78
76
  Requires-Dist: matplotlib; extra == "all"
79
- Requires-Dist: mpi4py; extra == "all"
80
77
  Requires-Dist: notebook; extra == "all"
81
78
  Requires-Dist: pandas; extra == "all"
82
- Requires-Dist: pyyaml; extra == "all"
83
79
  Provides-Extra: dev
84
80
  Requires-Dist: flake8; extra == "dev"
85
81
  Requires-Dist: pytest>=4.6; extra == "dev"
@@ -93,26 +89,26 @@ pyTMD
93
89
 
94
90
  |License|
95
91
  |Documentation Status|
96
- |Coverage Status|
97
92
  |PyPI|
98
93
  |conda-forge|
94
+ |commits-since|
99
95
  |zenodo|
100
96
 
101
- .. |License| image:: https://img.shields.io/github/license/tsutterley/pyTMD
102
- :target: https://github.com/tsutterley/pyTMD/blob/main/LICENSE
97
+ .. |License| image:: https://img.shields.io/github/license/pyTMD/pyTMD
98
+ :target: https://github.com/pyTMD/pyTMD/blob/main/LICENSE
103
99
 
104
100
  .. |Documentation Status| image:: https://readthedocs.org/projects/pytmd/badge/?version=latest
105
101
  :target: https://pytmd.readthedocs.io/en/latest/?badge=latest
106
102
 
107
- .. |Coverage Status| image:: https://codecov.io/gh/tsutterley/pyTMD/branch/main/graph/badge.svg
108
- :target: https://codecov.io/gh/tsutterley/pyTMD
109
-
110
103
  .. |PyPI| image:: https://img.shields.io/pypi/v/pyTMD.svg
111
104
  :target: https://pypi.python.org/pypi/pyTMD/
112
105
 
113
106
  .. |conda-forge| image:: https://img.shields.io/conda/vn/conda-forge/pytmd
114
107
  :target: https://anaconda.org/conda-forge/pytmd
115
108
 
109
+ .. |commits-since| image:: https://img.shields.io/github/commits-since/pyTMD/pyTMD/latest
110
+ :target: https://github.com/pyTMD/pyTMD/releases
111
+
116
112
  .. |zenodo| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.5555395.svg
117
113
  :target: https://doi.org/10.5281/zenodo.5555395
118
114
 
@@ -149,7 +145,7 @@ Development version from GitHub:
149
145
 
150
146
  .. code-block:: bash
151
147
 
152
- python3 -m pip install git+https://github.com/tsutterley/pyTMD.git
148
+ python3 -m pip install git+https://github.com/pyTMD/pyTMD.git
153
149
 
154
150
  Dependencies
155
151
  ############
@@ -178,9 +174,9 @@ Download
178
174
  ########
179
175
 
180
176
  | The program homepage is:
181
- | https://github.com/tsutterley/pyTMD
177
+ | https://github.com/pyTMD/pyTMD
182
178
  | A zip archive of the latest version is available directly at:
183
- | https://github.com/tsutterley/pyTMD/archive/main.zip
179
+ | https://github.com/pyTMD/pyTMD/archive/main.zip
184
180
 
185
181
  Alternative Software
186
182
  ####################
@@ -204,7 +200,7 @@ Contributing
204
200
  ############
205
201
 
206
202
  This project contains work and contributions from the `scientific community <./CONTRIBUTORS.rst>`_.
207
- If you would like to contribute to the project, please have a look at the `open issues <https://github.com/tsutterley/pyTMD/issues>`_ and `discussions board <https://github.com/tsutterley/pyTMD/discussions>`_.
203
+ If you would like to contribute to the project, please have a look at the `open issues <https://github.com/pyTMD/pyTMD/issues>`_ and `discussions board <https://github.com/pyTMD/pyTMD/discussions>`_.
208
204
 
209
205
  Credits
210
206
  #######
@@ -4,26 +4,26 @@ pyTMD
4
4
 
5
5
  |License|
6
6
  |Documentation Status|
7
- |Coverage Status|
8
7
  |PyPI|
9
8
  |conda-forge|
9
+ |commits-since|
10
10
  |zenodo|
11
11
 
12
- .. |License| image:: https://img.shields.io/github/license/tsutterley/pyTMD
13
- :target: https://github.com/tsutterley/pyTMD/blob/main/LICENSE
12
+ .. |License| image:: https://img.shields.io/github/license/pyTMD/pyTMD
13
+ :target: https://github.com/pyTMD/pyTMD/blob/main/LICENSE
14
14
 
15
15
  .. |Documentation Status| image:: https://readthedocs.org/projects/pytmd/badge/?version=latest
16
16
  :target: https://pytmd.readthedocs.io/en/latest/?badge=latest
17
17
 
18
- .. |Coverage Status| image:: https://codecov.io/gh/tsutterley/pyTMD/branch/main/graph/badge.svg
19
- :target: https://codecov.io/gh/tsutterley/pyTMD
20
-
21
18
  .. |PyPI| image:: https://img.shields.io/pypi/v/pyTMD.svg
22
19
  :target: https://pypi.python.org/pypi/pyTMD/
23
20
 
24
21
  .. |conda-forge| image:: https://img.shields.io/conda/vn/conda-forge/pytmd
25
22
  :target: https://anaconda.org/conda-forge/pytmd
26
23
 
24
+ .. |commits-since| image:: https://img.shields.io/github/commits-since/pyTMD/pyTMD/latest
25
+ :target: https://github.com/pyTMD/pyTMD/releases
26
+
27
27
  .. |zenodo| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.5555395.svg
28
28
  :target: https://doi.org/10.5281/zenodo.5555395
29
29
 
@@ -60,7 +60,7 @@ Development version from GitHub:
60
60
 
61
61
  .. code-block:: bash
62
62
 
63
- python3 -m pip install git+https://github.com/tsutterley/pyTMD.git
63
+ python3 -m pip install git+https://github.com/pyTMD/pyTMD.git
64
64
 
65
65
  Dependencies
66
66
  ############
@@ -89,9 +89,9 @@ Download
89
89
  ########
90
90
 
91
91
  | The program homepage is:
92
- | https://github.com/tsutterley/pyTMD
92
+ | https://github.com/pyTMD/pyTMD
93
93
  | A zip archive of the latest version is available directly at:
94
- | https://github.com/tsutterley/pyTMD/archive/main.zip
94
+ | https://github.com/pyTMD/pyTMD/archive/main.zip
95
95
 
96
96
  Alternative Software
97
97
  ####################
@@ -115,7 +115,7 @@ Contributing
115
115
  ############
116
116
 
117
117
  This project contains work and contributions from the `scientific community <./CONTRIBUTORS.rst>`_.
118
- If you would like to contribute to the project, please have a look at the `open issues <https://github.com/tsutterley/pyTMD/issues>`_ and `discussions board <https://github.com/tsutterley/pyTMD/discussions>`_.
118
+ If you would like to contribute to the project, please have a look at the `open issues <https://github.com/pyTMD/pyTMD/issues>`_ and `discussions board <https://github.com/pyTMD/pyTMD/discussions>`_.
119
119
 
120
120
  Credits
121
121
  #######
@@ -24,14 +24,9 @@ import pyTMD.utilities
24
24
  import pyTMD.version
25
25
  from pyTMD import io
26
26
  from pyTMD import solve
27
- from pyTMD.crs import (
28
- crs,
29
- datum,
30
- _ellipsoids
31
- )
27
+ from pyTMD.crs import crs
32
28
 
33
29
  # Deprecated functions
34
- from pyTMD.check_points import check_points
35
30
  from pyTMD.compute_tide_corrections import (
36
31
  compute_corrections,
37
32
  compute_tide_corrections,
@@ -40,8 +35,6 @@ from pyTMD.compute_tide_corrections import (
40
35
  compute_OPT_corrections,
41
36
  compute_SET_corrections,
42
37
  )
43
- import pyTMD.eop
44
- import pyTMD.time
45
38
 
46
39
  # get semantic version from setuptools-scm
47
40
  __version__ = pyTMD.version.version
@@ -40,6 +40,8 @@ REFERENCES:
40
40
 
41
41
  UPDATE HISTORY:
42
42
  Updated 02/2025: add option to make doodson numbers strings
43
+ add Doodson number convention for converting 11 to E
44
+ add Doodson (1921) table for coefficients missing from Cartwright tables
43
45
  Updated 12/2024: added function to calculate tidal aliasing periods
44
46
  Updated 11/2024: allow variable case for Doodson number formalisms
45
47
  fix species in constituent parameters for complex tides
@@ -1489,6 +1491,8 @@ def _love_numbers(
1489
1491
  # return the Love numbers for frequency
1490
1492
  return (h2, k2, l2)
1491
1493
 
1494
+ # Doodson (1921) table with values missing from Cartwright tables
1495
+ _d1921_table = get_data_path(['data','d1921_tab.txt'])
1492
1496
  # Cartwright and Tayler (1971) table with 3rd-degree values
1493
1497
  _ct1971_table_5 = get_data_path(['data','ct1971_tab5.txt'])
1494
1498
  # Cartwright and Edden (1973) table with updated values
@@ -1561,13 +1565,14 @@ def _to_doodson_number(coef: list | np.ndarray, **kwargs):
1561
1565
  # add 5 to values following Doodson convention (prevent negatives)
1562
1566
  coef[1:] += 5
1563
1567
  # check for unsupported constituents
1564
- if (np.any(coef < 0) or np.any(coef > 10)) and kwargs['raise_error']:
1568
+ if (np.any(coef < 0) or np.any(coef > 11)) and kwargs['raise_error']:
1565
1569
  raise ValueError('Unsupported constituent')
1566
- elif (np.any(coef < 0) or np.any(coef > 10)):
1570
+ elif (np.any(coef < 0) or np.any(coef > 11)):
1567
1571
  return None
1568
- elif np.any(coef == 10):
1569
- # convert to string and replace 10 with X (Cartwright convention)
1570
- DO = [str(v).replace('10','X') for v in coef]
1572
+ elif np.any(coef == 10) or np.any(coef == 11):
1573
+ # convert coefficients to strings
1574
+ # replace 10 with X and 11 with E (Doodson convention)
1575
+ DO = [str(v).replace('10','X').replace('11','E') for v in coef]
1571
1576
  # convert to Doodson number
1572
1577
  return np.str_('{0}{1}{2}.{3}{4}{5}'.format(*DO))
1573
1578
  else:
@@ -1614,8 +1619,9 @@ def _from_doodson_number(DO: str | float | np.ndarray, **kwargs):
1614
1619
  Doodson coefficients (Cartwright numbers) for constituent
1615
1620
  """
1616
1621
  # convert from Doodson number to Cartwright numbers
1617
- coef = [c.replace('X', '10') for c in re.findall(r'\w', str(DO).zfill(7))]
1618
- coef = np.array(coef, dtype=int)
1622
+ # replace 10 with X and 11 with E (Doodson convention)
1623
+ coef = np.array([c.replace('X', '10').replace('E', '11')
1624
+ for c in re.findall(r'\w', str(DO).zfill(7))], dtype=int)
1619
1625
  # remove 5 from values following Doodson convention
1620
1626
  coef[1:] -= 5
1621
1627
  return coef
@@ -8,8 +8,8 @@ PYTHON DEPENDENCIES:
8
8
  numpy: Scientific Computing Tools For Python
9
9
  https://numpy.org
10
10
  https://numpy.org/doc/stable/user/numpy-for-matlab-users.html
11
- PyEphem: Astronomical Ephemeris for Python
12
- https://rhodesmill.org/pyephem/
11
+ jplephem: Astronomical Ephemeris for Python
12
+ https://pypi.org/project/jplephem/
13
13
 
14
14
  REFERENCES:
15
15
  Jean Meeus, Astronomical Algorithms, 2nd edition, 1998.
@@ -960,7 +960,7 @@ def LPT_displacements(
960
960
 
961
961
  # validate input arguments
962
962
  assert TIME.lower() in ('gps', 'loran', 'tai', 'utc', 'datetime')
963
- assert ELLIPSOID.upper() in pyTMD._ellipsoids
963
+ assert ELLIPSOID.upper() in pyTMD.spatial._ellipsoids
964
964
  assert CONVENTION.isdigit() and CONVENTION in timescale.eop._conventions
965
965
  # determine input data type based on variable dimensions
966
966
  if not TYPE:
@@ -999,7 +999,7 @@ def LPT_displacements(
999
999
  # degrees to radians
1000
1000
  dtr = np.pi/180.0
1001
1001
  # earth and physical parameters for ellipsoid
1002
- units = pyTMD.datum(ellipsoid=ELLIPSOID, units='MKS')
1002
+ units = pyTMD.spatial.datum(ellipsoid=ELLIPSOID, units='MKS')
1003
1003
  # tidal love/shida numbers appropriate for the load tide
1004
1004
  hb2 = 0.6207
1005
1005
  lb2 = 0.0836
@@ -1167,7 +1167,7 @@ def OPT_displacements(
1167
1167
 
1168
1168
  # validate input arguments
1169
1169
  assert TIME.lower() in ('gps', 'loran', 'tai', 'utc', 'datetime')
1170
- assert ELLIPSOID.upper() in pyTMD._ellipsoids
1170
+ assert ELLIPSOID.upper() in pyTMD.spatial._ellipsoids
1171
1171
  assert CONVENTION.isdigit() and CONVENTION in timescale.eop._conventions
1172
1172
  assert METHOD.lower() in ('bilinear', 'spline', 'linear', 'nearest')
1173
1173
  # determine input data type based on variable dimensions
@@ -1214,7 +1214,7 @@ def OPT_displacements(
1214
1214
  # degrees to radians
1215
1215
  dtr = np.pi/180.0
1216
1216
  # earth and physical parameters for ellipsoid
1217
- units = pyTMD.datum(ellipsoid=ELLIPSOID, units='MKS')
1217
+ units = pyTMD.spatial.datum(ellipsoid=ELLIPSOID, units='MKS')
1218
1218
  # mean equatorial gravitational acceleration [m/s^2]
1219
1219
  ge = 9.7803278
1220
1220
  # density of sea water [kg/m^3]
@@ -1427,7 +1427,7 @@ def SET_displacements(
1427
1427
  nt = len(ts)
1428
1428
 
1429
1429
  # earth and physical parameters for ellipsoid
1430
- units = pyTMD.datum(ellipsoid=ELLIPSOID, units='MKS')
1430
+ units = pyTMD.spatial.datum(ellipsoid=ELLIPSOID, units='MKS')
1431
1431
 
1432
1432
  # convert input coordinates to cartesian
1433
1433
  X, Y, Z = pyTMD.spatial.to_cartesian(lon, lat,
@@ -0,0 +1,247 @@
1
+ #!/usr/bin/env python
2
+ u"""
3
+ crs.py
4
+ Written by Tyler Sutterley (09/2024)
5
+ Coordinates Reference System (CRS) class
6
+
7
+ CALLING SEQUENCE:
8
+ x, y = pyTMD.crs().convert(lon, lat, PROJ, 'F')
9
+ lon, lat = pyTMD.crs().convert(x, y, PROJ, 'B')
10
+
11
+ INPUTS:
12
+ i1: longitude ('F') or projection easting x ('B')
13
+ i2: latitude ('F') or projection northing y ('B')
14
+ PROJ: spatial reference system for coordinate transformations
15
+ BF: backwards ('B') or forward ('F') translations
16
+
17
+ OPTIONS:
18
+ EPSG: spatial reference system code for input (F) and output (B) coordinates
19
+
20
+ OUTPUTS:
21
+ o1: projection easting x ('F') or longitude ('B')
22
+ o2: projection northing y ('F') or latitude ('B')
23
+
24
+ PYTHON DEPENDENCIES:
25
+ numpy: Scientific Computing Tools For Python
26
+ https://numpy.org
27
+ https://numpy.org/doc/stable/user/numpy-for-matlab-users.html
28
+ pyproj: Python interface to PROJ library
29
+ https://pypi.org/project/pyproj/
30
+ https://pyproj4.github.io/pyproj/
31
+
32
+ UPDATE HISTORY:
33
+ Updated 09/2024: added function for idealized Arctic Azimuthal projection
34
+ complete refactor to use JSON dictionary format for model projections
35
+ Updated 07/2024: added function to get the CRS transform
36
+ Updated 05/2024: make subscriptable and allow item assignment
37
+ Updated 04/2024: use wrapper to importlib for optional dependencies
38
+ Updated 02/2024: changed class name for ellipsoid parameters to datum
39
+ Updated 12/2023: converted conversion functions to class
40
+ Updated 03/2023: add basic variable typing to function inputs
41
+ renamed coordinate reference system conversion functions
42
+ Updated 02/2023: use named exception before passing to custom
43
+ Updated 11/2022: place some imports within try/except statements
44
+ use f-strings for formatting verbose or ascii output
45
+ Updated 04/2022: updated docstrings to numpy documentation format
46
+ Updated 09/2021: added function for using custom projections
47
+ Updated 06/2021: added 3413 for new 1km Greenland model from ESR
48
+ Updated 08/2020: using conversion protocols following pyproj-2 updates
49
+ https://pyproj4.github.io/pyproj/stable/gotchas.html
50
+ Updated 07/2020: added function docstrings. changed function name
51
+ Updated 03/2020: remove commented coordinate conversion functions
52
+ Updated 11/2019: using pyproj for coordinate conversions
53
+ Written 09/2017
54
+ """
55
+
56
+ from __future__ import annotations
57
+
58
+ import logging
59
+ import numpy as np
60
+ from pyTMD.utilities import import_dependency
61
+ # attempt imports
62
+ pyproj = import_dependency('pyproj')
63
+
64
+ __all__ = [
65
+ 'crs',
66
+ ]
67
+
68
+ class crs:
69
+ """Coordinate Reference System transformations for tide models
70
+
71
+ Attributes
72
+ ----------
73
+ name: str
74
+ Projection name
75
+ transformer: obj
76
+ ``pyproj`` transformer for changing coordinate reference system
77
+ """
78
+ def __init__(self):
79
+ self.name = None
80
+ self.transformer = None
81
+ self._direction = None
82
+
83
+ def convert(self,
84
+ i1: np.ndarray,
85
+ i2: np.ndarray,
86
+ PROJ: str | dict,
87
+ BF: str,
88
+ EPSG: int | str = 4326
89
+ ):
90
+ """
91
+ Converts points to and from Coordinates Reference Systems (CRS)
92
+
93
+ Parameters
94
+ ----------
95
+ i1: np.ndarray
96
+ Input x-coordinates
97
+ i2: np.ndarray
98
+ Input y-coordinates
99
+ PROJ: str or dict
100
+ Spatial reference system for coordinate transformations
101
+ BF: str
102
+ Direction of transformation
103
+
104
+ - ``'B'``: backwards
105
+ - ``'F'``: forwards
106
+ EPSG: int or str, default 4326 (WGS84 Latitude/Longitude)
107
+ input (``'F'``) or output (``'B'``) coordinate system
108
+
109
+ Returns
110
+ -------
111
+ o1: np.ndarray
112
+ Output transformed x-coordinates
113
+ o2: np.ndarray
114
+ Output transformed y-coordinates
115
+ """
116
+ # name of the projection
117
+ self.name = PROJ
118
+ # get the CRS and transform direction
119
+ self.get(PROJ)
120
+ self._direction = BF[0].upper()
121
+ # run conversion program and return values
122
+ return self.transform(i1, i2, EPSG=EPSG)
123
+
124
+ # PURPOSE: try to get the projection information
125
+ def get(self, PROJ: str | dict):
126
+ """
127
+ Tries to get the coordinate reference system
128
+
129
+ Parameters
130
+ ----------
131
+ PROJ: str or dict
132
+ Spatial reference system for coordinate transformations
133
+ """
134
+ # get the coordinate reference system
135
+ try:
136
+ self.crs = self.from_input(PROJ)
137
+ self.name = self.crs.name
138
+ except Exception as exc:
139
+ pass
140
+ else:
141
+ return self
142
+ # projection not found or available
143
+ raise pyproj.exceptions.CRSError
144
+
145
+ def transform(self,
146
+ i1: np.ndarray,
147
+ i2: np.ndarray,
148
+ EPSG: int | str = 4326,
149
+ **kwargs):
150
+ """
151
+ Performs Coordinates Reference System (CRS) transformations
152
+
153
+ Parameters
154
+ ----------
155
+ i1: np.ndarray
156
+ Input x-coordinates
157
+ i2: np.ndarray
158
+ Input y-coordinates
159
+ EPSG: int or str, default 4326 (WGS84 Latitude/Longitude)
160
+ input (``'F'``) or output (``'B'``) coordinate system
161
+ kwargs: dict
162
+ Keyword arguments for the transformation
163
+
164
+ Returns
165
+ -------
166
+ o1: np.ndarray
167
+ Output transformed x-coordinates
168
+ o2: np.ndarray
169
+ Output transformed y-coordinates
170
+ """
171
+ # set the direction of the transformation
172
+ kwargs.setdefault('direction', self.direction)
173
+ # get the coordinate reference system and transform
174
+ source_crs = self.from_input(EPSG)
175
+ self.transformer = pyproj.Transformer.from_crs(
176
+ source_crs, self.crs, always_xy=True)
177
+ # convert coordinate reference system
178
+ o1, o2 = self.transformer.transform(i1, i2, **kwargs)
179
+ # return the transformed coordinates
180
+ return (o1, o2)
181
+
182
+ # PURPOSE: try to get the projection information
183
+ def from_input(self, PROJECTION: int | str | dict):
184
+ """
185
+ Attempt to retrieve the Coordinate Reference System
186
+
187
+ Parameters
188
+ ----------
189
+ PROJECTION: int, str or dict
190
+ Coordinate Reference System
191
+ """
192
+ # coordinate reference system dictoinary
193
+ try:
194
+ CRS = pyproj.CRS.from_user_input(PROJECTION)
195
+ except (ValueError, pyproj.exceptions.CRSError):
196
+ pass
197
+ else:
198
+ return CRS
199
+ # EPSG projection code
200
+ try:
201
+ CRS = pyproj.CRS.from_epsg(int(PROJECTION))
202
+ except (ValueError, pyproj.exceptions.CRSError):
203
+ pass
204
+ else:
205
+ return CRS
206
+ # coordinate reference system string
207
+ try:
208
+ CRS = pyproj.CRS.from_string(PROJECTION)
209
+ except (ValueError, pyproj.exceptions.CRSError):
210
+ pass
211
+ else:
212
+ return CRS
213
+ # no projection can be made
214
+ raise pyproj.exceptions.CRSError
215
+
216
+ @property
217
+ def direction(self):
218
+ """
219
+ ``pyproj`` direction of the coordinate transform
220
+ """
221
+ # convert from input coordinates to model coordinates
222
+ if (self._direction is None) or (self._direction.upper() == 'F'):
223
+ return pyproj.enums.TransformDirection.FORWARD
224
+ # convert from model coordinates to coordinates
225
+ elif (self._direction.upper() == 'B'):
226
+ return pyproj.enums.TransformDirection.INVERSE
227
+
228
+ @property
229
+ def is_geographic(self):
230
+ """
231
+ Check if the coordinate reference system is geographic
232
+ """
233
+ return self.crs.is_geographic
234
+
235
+ def __str__(self):
236
+ """String representation of the ``crs`` object
237
+ """
238
+ properties = ['pyTMD.crs']
239
+ properties.append(f" name: {self.name}")
240
+ properties.append(f" direction: {self.direction.name}")
241
+ return '\n'.join(properties)
242
+
243
+ def __getitem__(self, key):
244
+ return getattr(self, key)
245
+
246
+ def __setitem__(self, key, value):
247
+ setattr(self, key, value)
@@ -0,0 +1,21 @@
1
+ 0 5 -4 1 0 0 -0.00010 -0.00010 -0.00010 0X1.655 0.00023
2
+ 0 5 -2 -1 0 0 -0.00049 -0.00049 -0.00049 0X3.455 0.00116
3
+ 0 5 -2 -1 1 0 -0.00020 -0.00020 -0.00020 0X3.465 0.00048
4
+ 0 5 0 -3 0 0 -0.00019 -0.00019 -0.00019 0X5.255 0.00045
5
+ 0 5 0 -3 1 0 -0.00008 -0.00008 -0.00008 0X5.265 0.00019
6
+ 0 6 -4 0 0 0 -0.00005 -0.00005 -0.00005 0E1.555 0.00012
7
+ 0 6 -2 0 0 0 -0.00008 -0.00008 -0.00008 0E3.555 0.00019
8
+ 1 -5 0 4 0 0 -0.00008 -0.00008 -0.00008 105.955 0.00011
9
+ 1 -5 2 2 0 0 -0.00032 -0.00032 -0.00032 107.755 0.00046
10
+ 1 -5 4 0 0 0 -0.00019 -0.00019 -0.00019 109.555 0.00028
11
+ 1 5 -2 0 0 0 0.00035 0.00035 0.00035 1X3.555 -0.00050
12
+ 1 5 -2 0 1 0 0.00022 0.00022 0.00022 1X3.565 -0.00032
13
+ 1 5 0 -2 0 0 0.00029 0.00029 0.00029 1X5.355 -0.00041
14
+ 1 5 0 -2 1 0 0.00019 0.00019 0.00019 1X5.365 -0.00027
15
+ 1 6 -2 -1 0 0 0.00008 0.00008 0.00008 1E3.455 -0.00012
16
+ 2 -5 2 3 0 0 0.00010 0.00010 0.00010 207.855 0.00015
17
+ 2 -5 4 1 0 0 0.00013 0.00013 0.00013 209.655 0.00018
18
+ 2 5 -2 -1 0 0 0.00012 0.00012 0.00012 2X3.455 0.00017
19
+ 2 5 0 -1 0 0 0.00022 0.00022 0.00022 2X5.455 0.00032
20
+ 2 5 0 -1 1 0 0.00019 0.00019 0.00019 2X5.465 0.00028
21
+ 3 -3 2 1 0 0 0.00011 0.00011 0.00011 327.655 -0.00017
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  u"""
3
3
  constituents.py
4
- Written by Tyler Sutterley (11/2024)
4
+ Written by Tyler Sutterley (02/2025)
5
5
  Basic tide model constituent class
6
6
 
7
7
  PYTHON DEPENDENCIES:
@@ -10,6 +10,7 @@ PYTHON DEPENDENCIES:
10
10
  https://numpy.org/doc/stable/user/numpy-for-matlab-users.html
11
11
 
12
12
  UPDATE HISTORY:
13
+ Updated 02/2025: add RHO to rho1 to known mappable constituents
13
14
  Updated 11/2024: added property for Extended Doodson numbers
14
15
  Updated 10/2024: added property for the shape of constituent fields
15
16
  Updated 09/2024: add more known constituents to string parser function
@@ -241,13 +242,14 @@ class constituents:
241
242
  # include negative look-behind and look-ahead for complex cases
242
243
  cindex = [r'(?<!s)sa','ssa','mm','msf',r'mt(?!m)(?!ide)','mf','alpha1',
243
244
  '2q1','sigma1',r'(?<!2)q1','rho1',r'(?<!rh)(?<!o)(?<!s)o1','tau1',
244
- 'm1','chi1','pi1','p1','s1','k1','psi1','phi1','beta1','theta1','j1',
245
- 'oo1','2n2','mu2',r'(?<!2)n2','nu2',r'(?<!2s)m2(?!a)(?!b)',
246
- 'm2a','m2b','lambda2','l2','t2',r'(?<!mn)(?<!mk)(?<!ep)s2(?!0)',
247
- 'alpha2','beta2','delta2','gamma2','r2','k2',r'(?<!b)eta2',
248
- 'mns2','2sm2','m3','mk3','s3','mn4','m4','ms4','mk4','so1',
249
- r'(?<!m)s4','s5','m6','s6','s7','s8','m8','mks2','msqm','mtm',
250
- r'(?<!m)n4','eps2','ups1','z0','node']
245
+ 'm1','chi1','pi1',r'(?<!al)p1','s1','k1','psi1','phi1','beta1',
246
+ 'theta1','j1','oo1','2n2','mu2',r'(?<!2)n2','nu2',
247
+ r'(?<!2s)(?<!l)(?<!la)(?<!ga)m2(?!a)(?!b)','m2a','m2b','lambda2',
248
+ r'(?<!de)l2',r'(?<!be)t2',r'(?<!mn)(?<!mk)(?<!ep)s2(?!0)','alpha2',
249
+ 'beta2','delta2','gamma2','r2','k2',r'(?<!b)eta2','mns2','2sm2',
250
+ 'm3','mk3','s3','mn4','m4','ms4','mk4','so1',r'(?<!m)s4','s5','m6',
251
+ 's6','s7','s8','m8','mks2','msqm','mtm',r'(?<!m)n4','eps2','ups1',
252
+ 'z0','node']
251
253
  # compile regular expression
252
254
  # adding GOT prime nomenclature for 3rd degree constituents
253
255
  rx = re.compile(r'(' + '|'.join(cindex) + r')(\')?', re.IGNORECASE)
@@ -256,10 +258,12 @@ class constituents:
256
258
  return "".join(rx.findall(constituent)[0]).lower()
257
259
  # known remapped cases
258
260
  mapping = [('2n','2n2'), ('alp1', 'alpha1'), ('alp2', 'alpha2'),
259
- ('bet1', 'beta1'), ('bet2', 'beta2'), ('e2','eps2'),
260
- ('del2', 'delta2'), ('gam2', 'gamma2'),
261
- ('la2','lambda2'), ('lam2','lambda2'),
262
- ('sig1','sigma1'), ('the1', 'theta1')]
261
+ ('bet1', 'beta1'), ('bet2', 'beta2'), ('del2', 'delta2'),
262
+ ('e2','eps2'), ('ep2','eps2'), ('gam2', 'gamma2'),
263
+ ('la2','lambda2'), ('lam2','lambda2'), ('lm2','lambda2'),
264
+ ('msq', 'msqm'), ('omega0', 'node'), ('om0', 'node'),
265
+ ('rho', 'rho1'), ('sig1','sigma1'),
266
+ ('the', 'theta1'), ('the1', 'theta1')]
263
267
  # iterate over known remapped cases
264
268
  for m in mapping:
265
269
  # check if tide model is a remapped case