pyTMD 2.1.2__tar.gz → 2.1.3__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 (61) hide show
  1. {pytmd-2.1.2 → pytmd-2.1.3}/PKG-INFO +1 -1
  2. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/io/FES.py +7 -6
  3. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/io/model.py +193 -5
  4. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD.egg-info/PKG-INFO +1 -1
  5. pytmd-2.1.3/version.txt +1 -0
  6. pytmd-2.1.2/version.txt +0 -1
  7. {pytmd-2.1.2 → pytmd-2.1.3}/.dockerignore +0 -0
  8. {pytmd-2.1.2 → pytmd-2.1.3}/.gitignore +0 -0
  9. {pytmd-2.1.2 → pytmd-2.1.3}/CODE_OF_CONDUCT.rst +0 -0
  10. {pytmd-2.1.2 → pytmd-2.1.3}/CONTRIBUTORS.rst +0 -0
  11. {pytmd-2.1.2 → pytmd-2.1.3}/LICENSE +0 -0
  12. {pytmd-2.1.2 → pytmd-2.1.3}/MANIFEST.in +0 -0
  13. {pytmd-2.1.2 → pytmd-2.1.3}/README.rst +0 -0
  14. {pytmd-2.1.2 → pytmd-2.1.3}/postBuild +0 -0
  15. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/__init__.py +0 -0
  16. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/arguments.py +0 -0
  17. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/astro.py +0 -0
  18. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/check_points.py +0 -0
  19. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/compute.py +0 -0
  20. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/compute_tide_corrections.py +0 -0
  21. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/crs.py +0 -0
  22. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/data/opoleloadcoefcmcor.txt.gz +0 -0
  23. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/data/tab5.2e.txt +0 -0
  24. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/data/tab5.3a.txt +0 -0
  25. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/data/tab5.3b.txt +0 -0
  26. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/ellipse.py +0 -0
  27. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/eop.py +0 -0
  28. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/interpolate.py +0 -0
  29. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/io/ATLAS.py +0 -0
  30. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/io/GOT.py +0 -0
  31. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/io/OTIS.py +0 -0
  32. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/io/__init__.py +0 -0
  33. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/io/constituents.py +0 -0
  34. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/io/ocean_pole_tide.py +0 -0
  35. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/predict.py +0 -0
  36. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/solve/__init__.py +0 -0
  37. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/solve/constants.py +0 -0
  38. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/spatial.py +0 -0
  39. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/time.py +0 -0
  40. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/tools.py +0 -0
  41. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/utilities.py +0 -0
  42. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD/version.py +0 -0
  43. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD.egg-info/SOURCES.txt +0 -0
  44. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD.egg-info/dependency_links.txt +0 -0
  45. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD.egg-info/requires.txt +0 -0
  46. {pytmd-2.1.2 → pytmd-2.1.3}/pyTMD.egg-info/top_level.txt +0 -0
  47. {pytmd-2.1.2 → pytmd-2.1.3}/requirements-dev.txt +0 -0
  48. {pytmd-2.1.2 → pytmd-2.1.3}/requirements.txt +0 -0
  49. {pytmd-2.1.2 → pytmd-2.1.3}/scripts/arcticdata_tides.py +0 -0
  50. {pytmd-2.1.2 → pytmd-2.1.3}/scripts/aviso_fes_tides.py +0 -0
  51. {pytmd-2.1.2 → pytmd-2.1.3}/scripts/compute_LPET_elevations.py +0 -0
  52. {pytmd-2.1.2 → pytmd-2.1.3}/scripts/compute_LPT_displacements.py +0 -0
  53. {pytmd-2.1.2 → pytmd-2.1.3}/scripts/compute_OPT_displacements.py +0 -0
  54. {pytmd-2.1.2 → pytmd-2.1.3}/scripts/compute_SET_displacements.py +0 -0
  55. {pytmd-2.1.2 → pytmd-2.1.3}/scripts/compute_tidal_currents.py +0 -0
  56. {pytmd-2.1.2 → pytmd-2.1.3}/scripts/compute_tidal_elevations.py +0 -0
  57. {pytmd-2.1.2 → pytmd-2.1.3}/scripts/reduce_OTIS_files.py +0 -0
  58. {pytmd-2.1.2 → pytmd-2.1.3}/scripts/usap_cats_tides.py +0 -0
  59. {pytmd-2.1.2 → pytmd-2.1.3}/scripts/verify_box_tpxo.py +0 -0
  60. {pytmd-2.1.2 → pytmd-2.1.3}/setup.cfg +0 -0
  61. {pytmd-2.1.2 → pytmd-2.1.3}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyTMD
3
- Version: 2.1.2
3
+ Version: 2.1.3
4
4
  Summary: Tide Model Driver to read OTIS, GOT and FES formatted tidal solutions and make tidal predictions
5
5
  Home-page: https://github.com/tsutterley/pyTMD
6
6
  Author: Tyler Sutterley
@@ -58,6 +58,7 @@ PROGRAM DEPENDENCIES:
58
58
 
59
59
  UPDATE HISTORY:
60
60
  Updated 07/2024: added new FES2022 to available known model versions
61
+ FES2022 have masked longitudes, only extract longitude data
61
62
  Updated 01/2024: attempt to extract constituent IDs from filenames
62
63
  Updated 06/2023: extract ocean tide model variables for FES2012
63
64
  Updated 04/2023: added global HAMTIDE11 model
@@ -675,18 +676,18 @@ def read_netcdf_file(
675
676
  # variable dimensions for each model
676
677
  # amplitude and phase components for each type
677
678
  if kwargs['version'] in ('FES2012',):
678
- lon = fileID.variables['lon'][:]
679
- lat = fileID.variables['lat'][:]
679
+ lon = fileID.variables['lon'][:].data
680
+ lat = fileID.variables['lat'][:].data
680
681
  amp_key = dict(z='Ha', u='Ua', v='Va')[kwargs['type']]
681
682
  phase_key = dict(z='Hg', u='Ug', v='Vg')[kwargs['type']]
682
683
  elif kwargs['version'] in ('FES2014','FES2022','EOT20'):
683
- lon = fileID.variables['lon'][:]
684
- lat = fileID.variables['lat'][:]
684
+ lon = fileID.variables['lon'][:].data
685
+ lat = fileID.variables['lat'][:].data
685
686
  amp_key = dict(z='amplitude', u='Ua', v='Va')[kwargs['type']]
686
687
  phase_key = dict(z='phase', u='Ug', v='Vg')[kwargs['type']]
687
688
  elif kwargs['version'] in ('HAMTIDE11',):
688
- lon = fileID.variables['LON'][:]
689
- lat = fileID.variables['LAT'][:]
689
+ lon = fileID.variables['LON'][:].data
690
+ lat = fileID.variables['LAT'][:].data
690
691
  amp_key = dict(z='AMPL', u='UAMP', v='VAMP')[kwargs['type']]
691
692
  phase_key = dict(z='PHAS', u='UPHA', v='VPHA')[kwargs['type']]
692
693
  # get amplitude and phase components
@@ -7,6 +7,7 @@ Retrieves tide model parameters for named tide models and
7
7
 
8
8
  UPDATE HISTORY:
9
9
  Updated 07/2024: added new FES2022 and FES2022_load to list of models
10
+ added JSON format for model definition files
10
11
  Updated 05/2024: make subscriptable and allow item assignment
11
12
  Updated 04/2024: append v-components of velocity only to netcdf format
12
13
  Updated 11/2023: revert TPXO9-atlas currents changes to separate dicts
@@ -44,6 +45,7 @@ from __future__ import annotations
44
45
  import re
45
46
  import io
46
47
  import copy
48
+ import json
47
49
  import pathlib
48
50
 
49
51
  class model:
@@ -1337,7 +1339,10 @@ class model:
1337
1339
  # return the complete output path
1338
1340
  return output_file
1339
1341
 
1340
- def from_file(self, definition_file: str | pathlib.Path | io.IOBase):
1342
+ def from_file(self,
1343
+ definition_file: str | pathlib.Path | io.IOBase,
1344
+ format: str = 'ascii'
1345
+ ):
1341
1346
  """
1342
1347
  Create a model object from an input definition file
1343
1348
 
@@ -1345,23 +1350,45 @@ class model:
1345
1350
  ----------
1346
1351
  definition_file: str, pathlib.Path or io.IOBase
1347
1352
  model definition file for creating model object
1353
+ format: str
1354
+ format of the input definition file
1355
+
1356
+ - ``'ascii'`` for tab-delimited definition file
1357
+ - ``'json'`` for JSON formatted definition file
1348
1358
  """
1349
- # variable with parameter definitions
1350
- parameters = {}
1351
1359
  # Opening definition file and assigning file ID number
1352
1360
  if isinstance(definition_file, io.IOBase):
1353
1361
  fid = copy.copy(definition_file)
1354
1362
  else:
1355
1363
  definition_file = pathlib.Path(definition_file).expanduser()
1356
1364
  fid = definition_file.open(mode="r", encoding='utf8')
1365
+ # load and parse definition file type
1366
+ if (format.lower() == 'ascii'):
1367
+ self.from_ascii(fid)
1368
+ elif (format.lower() == 'json'):
1369
+ self.from_json(fid)
1370
+ # close the definition file
1371
+ fid.close()
1372
+ # return the model object
1373
+ return self
1374
+
1375
+ def from_ascii(self, fid: io.IOBase):
1376
+ """
1377
+ Load and parse tab-delimited definition file
1378
+
1379
+ Parameters
1380
+ ----------
1381
+ fid: io.IOBase
1382
+ open definition file object
1383
+ """
1384
+ # variable with parameter definitions
1385
+ parameters = {}
1357
1386
  # for each line in the file will extract the parameter (name and value)
1358
1387
  for fileline in fid:
1359
1388
  # Splitting the input line between parameter name and value
1360
1389
  part = fileline.rstrip().split(maxsplit=1)
1361
1390
  # filling the parameter definition variable
1362
1391
  parameters[part[0]] = part[1]
1363
- # close the parameter file
1364
- fid.close()
1365
1392
  # convert from dictionary to model variable
1366
1393
  temp = self.from_dict(parameters)
1367
1394
  # verify model name, format and type
@@ -1539,6 +1566,167 @@ class model:
1539
1566
  # return the model parameters
1540
1567
  return temp
1541
1568
 
1569
+ def from_json(self, fid: io.IOBase):
1570
+ """
1571
+ Load and parse JSON definition file
1572
+
1573
+ Parameters
1574
+ ----------
1575
+ fid: io.IOBase
1576
+ open definition file object
1577
+ """
1578
+ # load JSON file
1579
+ parameters = json.load(fid)
1580
+ # convert from dictionary to model variable
1581
+ temp = self.from_dict(parameters)
1582
+ # verify model name, format and type
1583
+ assert temp.name
1584
+ assert temp.format in ('OTIS','ATLAS','TMD3','netcdf','GOT','FES')
1585
+ assert temp.type
1586
+ assert temp.model_file
1587
+ # split model file into list if an ATLAS, GOT or FES file
1588
+ # model files can be comma, tab or space delimited
1589
+ # extract full path to tide model files
1590
+ # extract full path to tide grid file
1591
+ if temp.format in ('OTIS','ATLAS','TMD3'):
1592
+ assert temp.grid_file
1593
+ # check if grid file is relative
1594
+ if (temp.directory is not None):
1595
+ temp.grid_file = temp.directory.joinpath(temp.grid_file).resolve()
1596
+ else:
1597
+ temp.grid_file = pathlib.Path(temp.grid_file).expanduser()
1598
+ # extract model files
1599
+ if (temp.type == ['u','v']) and (temp.directory is not None):
1600
+ # use glob strings to find files in directory
1601
+ for key, glob_string in temp.model_file.items():
1602
+ temp.model_file[key] = list(temp.directory.glob(glob_string))
1603
+ # attempt to extract model directory
1604
+ try:
1605
+ temp.model_directory = temp.model_file['u'][0].parent
1606
+ except (IndexError, AttributeError) as exc:
1607
+ message = f'No model files found with {glob_string}'
1608
+ raise FileNotFoundError(message) from exc
1609
+ elif (temp.type == 'z') and (temp.directory is not None):
1610
+ # use glob strings to find files in directory
1611
+ glob_string = copy.copy(temp.model_file)
1612
+
1613
+ temp.model_file = list(temp.directory.glob(glob_string))
1614
+ # attempt to extract model directory
1615
+ try:
1616
+ temp.model_directory = temp.model_file[0].parent
1617
+ except (IndexError, AttributeError) as exc:
1618
+ message = f'No model files found with {glob_string}'
1619
+ raise FileNotFoundError(message) from exc
1620
+ elif (temp.type == ['u','v']) and isinstance(temp.model_file, dict):
1621
+ # resolve paths to model files for each direction
1622
+ for key, model_file in temp.model_file.items():
1623
+ temp.model_file[key] = [pathlib.Path(f).expanduser() for f in
1624
+ model_file]
1625
+ # copy directory dictionaries
1626
+ temp.model_directory = temp.model_file['u'][0].parent
1627
+ elif (temp.type == 'z') and isinstance(temp.model_file, list):
1628
+ # resolve paths to model files
1629
+ temp.model_file = [pathlib.Path(f).expanduser() for f in
1630
+ temp.model_file]
1631
+ temp.model_directory = temp.model_file[0].parent
1632
+ else:
1633
+ # fully defined single file case
1634
+ temp.model_file = pathlib.Path(temp.model_file).expanduser()
1635
+ temp.model_directory = temp.model_file.parent
1636
+ elif temp.format in ('netcdf',):
1637
+ assert temp.grid_file
1638
+ # check if grid file is relative
1639
+ if (temp.directory is not None):
1640
+ temp.grid_file = temp.directory.joinpath(temp.grid_file).resolve()
1641
+ else:
1642
+ temp.grid_file = pathlib.Path(temp.grid_file).expanduser()
1643
+ # extract model files
1644
+ if (temp.type == ['u','v']) and (temp.directory is not None):
1645
+ # use glob strings to find files in directory
1646
+ for key, glob_string in temp.model_file.items():
1647
+ temp.model_file[key] = list(temp.directory.glob(glob_string))
1648
+ # attempt to extract model directory
1649
+ try:
1650
+ temp.model_directory = temp.model_file['u'][0].parent
1651
+ except (IndexError, AttributeError) as exc:
1652
+ message = f'No model files found with {glob_string}'
1653
+ raise FileNotFoundError(message) from exc
1654
+ elif (temp.type == 'z') and (temp.directory is not None):
1655
+ # use glob strings to find files in directory
1656
+ glob_string = copy.copy(temp.model_file)
1657
+ temp.model_file = list(temp.directory.glob(glob_string))
1658
+ # attempt to extract model directory
1659
+ try:
1660
+ temp.model_directory = temp.model_file[0].parent
1661
+ except (IndexError, AttributeError) as exc:
1662
+ message = f'No model files found with {glob_string}'
1663
+ raise FileNotFoundError(message) from exc
1664
+ elif (temp.type == ['u','v']):
1665
+ # resolve paths to model files for each direction
1666
+ for key, model_file in temp.model_file.items():
1667
+ temp.model_file[key] = [pathlib.Path(f).expanduser() for f in
1668
+ model_file]
1669
+ # copy to directory dictionaries
1670
+ temp.model_directory = temp.model_file['u'][0].parent
1671
+ elif (temp.type == 'z'):
1672
+ # resolve paths to model files
1673
+ temp.model_file = [pathlib.Path(f).expanduser() for f in
1674
+ temp.model_file]
1675
+ temp.model_directory = temp.model_file[0].parent
1676
+ elif temp.format in ('FES','GOT'):
1677
+ # extract model files
1678
+ if (temp.type == ['u','v']) and (temp.directory is not None):
1679
+ # use glob strings to find files in directory
1680
+ for key, glob_string in temp.model_file.items():
1681
+ temp.model_file[key] = list(temp.directory.glob(glob_string))
1682
+ # build model directory dictionaries
1683
+ temp.model_directory = {}
1684
+ for key, val in temp.model_file.items():
1685
+ # attempt to extract model directory
1686
+ try:
1687
+ temp.model_directory[key] = val[0].parent
1688
+ except (IndexError, AttributeError) as exc:
1689
+ message = f'No model files found with {glob_string[key]}'
1690
+ raise FileNotFoundError(message) from exc
1691
+ elif (temp.type == 'z') and (temp.directory is not None):
1692
+ # use glob strings to find files in directory
1693
+ glob_string = copy.copy(temp.model_file)
1694
+
1695
+ temp.model_file = list(temp.directory.glob(glob_string))
1696
+ # attempt to extract model directory
1697
+ try:
1698
+ temp.model_directory = temp.model_file[0].parent
1699
+ except (IndexError, AttributeError) as exc:
1700
+ message = f'No model files found with {glob_string}'
1701
+ elif (temp.type == ['u','v']):
1702
+ # resolve paths to model files for each direction
1703
+ for key, model_file in temp.model_file.items():
1704
+ temp.model_file[key] = [pathlib.Path(f).expanduser() for f in
1705
+ model_file]
1706
+ # build model directory dictionaries
1707
+ temp.model_directory = {}
1708
+ for key, val in temp.model_file.items():
1709
+ temp.model_directory[key] = val[0].parent
1710
+ elif (temp.type == 'z'):
1711
+ # resolve paths to model files
1712
+ temp.model_file = [pathlib.Path(f).expanduser() for f in
1713
+ temp.model_file]
1714
+ temp.model_directory = temp.model_file[0].parent
1715
+ # verify that projection attribute exists for projected models
1716
+ if temp.format in ('OTIS','ATLAS','TMD3'):
1717
+ assert temp.projection
1718
+ # convert scale from string to float
1719
+ if temp.format in ('netcdf','GOT','FES'):
1720
+ assert temp.scale
1721
+ # assert that FES model has a version
1722
+ # get model constituents from constituent files
1723
+ if temp.format in ('FES',):
1724
+ assert temp.version
1725
+ if (temp.constituents is None):
1726
+ temp.parse_constituents()
1727
+ # return the model parameters
1728
+ return temp
1729
+
1542
1730
  def parse_constituents(self) -> list:
1543
1731
  """
1544
1732
  Parses tide model files for a list of model constituents
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyTMD
3
- Version: 2.1.2
3
+ Version: 2.1.3
4
4
  Summary: Tide Model Driver to read OTIS, GOT and FES formatted tidal solutions and make tidal predictions
5
5
  Home-page: https://github.com/tsutterley/pyTMD
6
6
  Author: Tyler Sutterley
@@ -0,0 +1 @@
1
+ 2.1.3
pytmd-2.1.2/version.txt DELETED
@@ -1 +0,0 @@
1
- 2.1.2
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes