Skip to content

Commit

Permalink
feat: can read from netCDF4 or HDF5 variable groups (#249)
Browse files Browse the repository at this point in the history
fix: spelling mistakes
  • Loading branch information
tsutterley authored Oct 26, 2023
1 parent dd7c961 commit a10f894
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 16 deletions.
10 changes: 5 additions & 5 deletions pyTMD/io/OTIS.py
Original file line number Diff line number Diff line change
Expand Up @@ -1133,7 +1133,7 @@ def read_otis_elevation(
input_file: str or pathlib.Path
input elevation file
ic: int
index of consituent
index of constituent
Returns
-------
Expand Down Expand Up @@ -1183,7 +1183,7 @@ def read_atlas_elevation(
input_file: str or pathlib.Path
input ATLAS elevation file
ic: int
index of consituent
index of constituent
constituent: str
tidal constituent ID
Expand Down Expand Up @@ -1282,7 +1282,7 @@ def read_otis_transport(
input_file: str or pathlib.Path
input transport file
ic: int
index of consituent
index of constituent
Returns
-------
Expand Down Expand Up @@ -1340,7 +1340,7 @@ def read_atlas_transport(
input_file: str or pathlib.Path
input ATLAS transport file
ic: int
index of consituent
index of constituent
constituent: str
tidal constituent ID
Expand Down Expand Up @@ -1652,7 +1652,7 @@ def read_netcdf_file(
input_file: str or pathlib.Path
input transport file
ic: int
index of consituent
index of constituent
variable: str or NoneType, default None
Tidal variable to read
Expand Down
31 changes: 21 additions & 10 deletions pyTMD/spatial.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
u"""
spatial.py
Written by Tyler Sutterley (09/2023)
Written by Tyler Sutterley (10/2023)
Utilities for reading, writing and operating on spatial data
Expand All @@ -22,6 +22,7 @@
constants.py: calculate reference parameters for common ellipsoids
UPDATE HISTORY:
Updated 10/2023: can read from netCDF4 or HDF5 variable groups
Updated 09/2023: add function to invert field mapping keys and values
use datetime64[ns] for parsing dates from ascii files
Updated 08/2023: remove possible crs variables from output fields list
Expand Down Expand Up @@ -304,6 +305,8 @@ def from_netCDF4(filename: str, **kwargs):
full path of input netCDF4 file
compression: str or NoneType, default None
file compression type
group: str or NoneType, default None
netCDF4 variable group
timename: str, default 'time'
name for time-dimension variable
xname: str, default 'lon'
Expand All @@ -317,6 +320,7 @@ def from_netCDF4(filename: str, **kwargs):
"""
# set default keyword arguments
kwargs.setdefault('compression', None)
kwargs.setdefault('group', None)
kwargs.setdefault('timename', 'time')
kwargs.setdefault('xname', 'lon')
kwargs.setdefault('yname', 'lat')
Expand Down Expand Up @@ -359,19 +363,21 @@ def from_netCDF4(filename: str, **kwargs):
kwargs['field_mapping']['data'] = copy.copy(kwargs['varname'])
if kwargs['timename'] is not None:
kwargs['field_mapping']['time'] = copy.copy(kwargs['timename'])
# check if reading from root group or sub-group
group = fileID.groups[kwargs['group']] if kwargs['group'] else fileID
# for each variable
for key, nc in kwargs['field_mapping'].items():
# Getting the data from each NetCDF variable
dinput[key] = fileID.variables[nc][:]
dinput[key] = group.variables[nc][:]
# get attributes for the included variables
dinput['attributes'][key] = {}
for attr in attributes_list:
# try getting the attribute
try:
ncattr, = [s for s in fileID.variables[nc].ncattrs()
ncattr, = [s for s in group.variables[nc].ncattrs()
if re.match(attr, s, re.I)]
dinput['attributes'][key][attr] = \
fileID.variables[nc].getncattr(ncattr)
group.variables[nc].getncattr(ncattr)
except (ValueError, AttributeError):
pass
# get projection information if there is a grid_mapping attribute
Expand All @@ -380,9 +386,9 @@ def from_netCDF4(filename: str, **kwargs):
grid_mapping = dinput['attributes']['data']['grid_mapping']
# get coordinate reference system attributes
dinput['attributes']['crs'] = {}
for att_name in fileID[grid_mapping].ncattrs():
for att_name in group[grid_mapping].ncattrs():
dinput['attributes']['crs'][att_name] = \
fileID.variables[grid_mapping].getncattr(att_name)
group.variables[grid_mapping].getncattr(att_name)
# get the spatial projection reference information from wkt
# and overwrite the file-level projection attribute (if existing)
srs = osgeo.osr.SpatialReference()
Expand All @@ -408,6 +414,8 @@ def from_HDF5(filename: str | pathlib.Path, **kwargs):
full path of input HDF5 file
compression: str or NoneType, default None
file compression type
group: str or NoneType, default None
netCDF4 variable group
timename: str, default 'time'
name for time-dimension variable
xname: str, default 'lon'
Expand All @@ -421,6 +429,7 @@ def from_HDF5(filename: str | pathlib.Path, **kwargs):
"""
# set default keyword arguments
kwargs.setdefault('compression', None)
kwargs.setdefault('group', None)
kwargs.setdefault('timename', 'time')
kwargs.setdefault('xname', 'lon')
kwargs.setdefault('yname', 'lat')
Expand Down Expand Up @@ -468,16 +477,18 @@ def from_HDF5(filename: str | pathlib.Path, **kwargs):
kwargs['field_mapping']['data'] = copy.copy(kwargs['varname'])
if kwargs['timename'] is not None:
kwargs['field_mapping']['time'] = copy.copy(kwargs['timename'])
# check if reading from root group or sub-group
group = fileID[kwargs['group']] if kwargs['group'] else fileID
# for each variable
for key, h5 in kwargs['field_mapping'].items():
# Getting the data from each HDF5 variable
dinput[key] = np.copy(fileID[h5][:])
dinput[key] = np.copy(group[h5][:])
# get attributes for the included variables
dinput['attributes'][key] = {}
for attr in attributes_list:
# try getting the attribute
try:
dinput['attributes'][key][attr] = fileID[h5].attrs[attr]
dinput['attributes'][key][attr] = group[h5].attrs[attr]
except (KeyError, AttributeError):
pass
# get projection information if there is a grid_mapping attribute
Expand All @@ -486,7 +497,7 @@ def from_HDF5(filename: str | pathlib.Path, **kwargs):
grid_mapping = dinput['attributes']['data']['grid_mapping']
# get coordinate reference system attributes
dinput['attributes']['crs'] = {}
for att_name, att_val in fileID[grid_mapping].attrs.items():
for att_name, att_val in group[grid_mapping].attrs.items():
dinput['attributes']['crs'][att_name] = att_val
# get the spatial projection reference information from wkt
# and overwrite the file-level projection attribute (if existing)
Expand Down Expand Up @@ -1090,7 +1101,7 @@ def convert_ellipsoid(
.. [1] J. Meeus, *Astronomical Algorithms*, 2nd edition, 477 pp., (1998).
"""
if (len(phi1) != len(h1)):
raise ValueError('phi and h have incompatable dimensions')
raise ValueError('phi and h have incompatible dimensions')
# semiminor axis of input and output ellipsoid
b1 = (1.0 - f1)*a1
b2 = (1.0 - f2)*a2
Expand Down
2 changes: 1 addition & 1 deletion pyTMD/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,7 @@ def get_leap_seconds(truncate: bool = True):
# convert from time of 2nd leap second to time of 1st leap second
leap_GPS = convert_delta_time(leap_UTC + TAI_UTC - TAI_GPS - 1,
epoch1=_ntp_epoch, epoch2=_gps_epoch)
# return the GPS times of leap second occurance
# return the GPS times of leap second occurrence
if truncate:
return leap_GPS[leap_GPS >= 0].astype(np.float64)
else:
Expand Down

0 comments on commit a10f894

Please sign in to comment.