Skip to content

Commit

Permalink
fix: FES2022 extrapolated data have zeroed out inland water bodies for
Browse files Browse the repository at this point in the history
…#309

feat: added option to use JSON format definition files
feat: add definition files for FES2022-extrapolated
  • Loading branch information
tsutterley committed Jul 19, 2024
1 parent 512c3df commit 2a16ea7
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 30 deletions.
79 changes: 53 additions & 26 deletions pyTMD/compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
UPDATE HISTORY:
Updated 07/2024: assert that data type is a known value
make number of days to convert JD to MJD a variable
added option to crop tide models to the domain of the input data
added option to use JSON format definition files
Updated 06/2024: use np.clongdouble instead of np.longcomplex
Updated 04/2024: use wrapper to importlib for optional dependencies
Updated 02/2024: changed class name for ellipsoid parameters to datum
Expand Down Expand Up @@ -114,6 +116,7 @@
import logging
import pathlib
import numpy as np
from io import IOBase
import scipy.interpolate
import pyTMD.crs
import pyTMD.io
Expand Down Expand Up @@ -183,7 +186,10 @@ def tide_elevations(
MODEL: str | None = None,
ATLAS_FORMAT: str = 'netcdf',
GZIP: bool = False,
DEFINITION_FILE: str | pathlib.Path | None = None,
DEFINITION_FILE: str | pathlib.Path | IOBase | None = None,
DEFINITION_FORMAT: str = 'ascii',
CROP: bool = False,
BOUNDS: list | np.ndarray | None = None,
EPSG: str | int = 3031,
EPOCH: list | tuple = (2000, 1, 1, 0, 0, 0),
TYPE: str | None = 'drift',
Expand Down Expand Up @@ -219,8 +225,17 @@ def tide_elevations(
- ``'netcdf'``
GZIP: bool, default False
Tide model files are gzip compressed
DEFINITION_FILE: str or NoneType, default None
DEFINITION_FILE: str, pathlib.Path, io.IOBase or NoneType, default None
Tide model definition file for use
DEFINITION_FORMAT: str, default 'ascii'
Format for model definition file
- ``'ascii'``: tab-delimited definition file
- ``'json'``: JSON formatted definition file
CROP: bool, default False
Crop tide model data to (buffered) bounds
BOUNDS: list, np.ndarray or NoneType, default None
Boundaries for cropping tide model data
EPSG: int, default: 3031 (Polar Stereographic South, WGS84)
Input coordinate system
EPOCH: tuple, default (2000,1,1,0,0,0)
Expand Down Expand Up @@ -280,8 +295,8 @@ def tide_elevations(

# get parameters for tide model
if DEFINITION_FILE is not None:
model = pyTMD.io.model(DIRECTORY).from_file(
pathlib.Path(DEFINITION_FILE).expanduser())
model = pyTMD.io.model(DIRECTORY).from_file(DEFINITION_FILE,

Check warning on line 298 in pyTMD/compute.py

View check run for this annotation

Codecov / codecov/patch

pyTMD/compute.py#L298

Added line #L298 was not covered by tests
format=DEFINITION_FORMAT)
else:
model = pyTMD.io.model(DIRECTORY, format=ATLAS_FORMAT,
compressed=GZIP).elevation(MODEL)
Expand Down Expand Up @@ -323,28 +338,28 @@ def tide_elevations(
if model.format in ('OTIS', 'ATLAS', 'TMD3'):
amp,ph,D,c = pyTMD.io.OTIS.extract_constants(lon, lat, model.grid_file,
model.model_file, model.projection, type=model.type,
method=METHOD, extrapolate=EXTRAPOLATE, cutoff=CUTOFF,
grid=model.format, apply_flexure=APPLY_FLEXURE)
crop=CROP, bounds=BOUNDS, method=METHOD, extrapolate=EXTRAPOLATE,
cutoff=CUTOFF, grid=model.format, apply_flexure=APPLY_FLEXURE)
# use delta time at 2000.0 to match TMD outputs
deltat = np.zeros((nt), dtype=np.float64)
elif (model.format == 'netcdf'):
amp,ph,D,c = pyTMD.io.ATLAS.extract_constants(lon, lat, model.grid_file,
model.model_file, type=model.type, method=METHOD,
extrapolate=EXTRAPOLATE, cutoff=CUTOFF, scale=model.scale,
compressed=model.compressed)
model.model_file, type=model.type, crop=CROP, bounds=BOUNDS,
method=METHOD, extrapolate=EXTRAPOLATE, cutoff=CUTOFF,
scale=model.scale, compressed=model.compressed)
# use delta time at 2000.0 to match TMD outputs
deltat = np.zeros((nt), dtype=np.float64)
elif (model.format == 'GOT'):
amp,ph,c = pyTMD.io.GOT.extract_constants(lon, lat, model.model_file,
method=METHOD, extrapolate=EXTRAPOLATE, cutoff=CUTOFF,
scale=model.scale, compressed=model.compressed)
crop=CROP, bounds=BOUNDS, method=METHOD, extrapolate=EXTRAPOLATE,
cutoff=CUTOFF, scale=model.scale, compressed=model.compressed)
# delta time (TT - UT1)
deltat = ts.tt_ut1
elif (model.format == 'FES'):
amp,ph = pyTMD.io.FES.extract_constants(lon, lat, model.model_file,
type=model.type, version=model.version, method=METHOD,
extrapolate=EXTRAPOLATE, cutoff=CUTOFF, scale=model.scale,
compressed=model.compressed)
type=model.type, version=model.version, crop=CROP, bounds=BOUNDS,
method=METHOD, extrapolate=EXTRAPOLATE, cutoff=CUTOFF,
scale=model.scale, compressed=model.compressed)
# available model constituents
c = model.constituents
# delta time (TT - UT1)
Expand Down Expand Up @@ -412,7 +427,10 @@ def tide_currents(
MODEL: str | None = None,
ATLAS_FORMAT: str = 'netcdf',
GZIP: bool = False,
DEFINITION_FILE: str | pathlib.Path | None = None,
DEFINITION_FILE: str | pathlib.Path | IOBase | None = None,
DEFINITION_FORMAT: str = 'ascii',
CROP: bool = False,
BOUNDS: list | np.ndarray | None = None,
EPSG: str | int = 3031,
EPOCH: list | tuple = (2000, 1, 1, 0, 0, 0),
TYPE: str | None = 'drift',
Expand Down Expand Up @@ -447,8 +465,17 @@ def tide_currents(
- ``'netcdf'``
GZIP: bool, default False
Tide model files are gzip compressed
DEFINITION_FILE: str or NoneType, default None
DEFINITION_FILE: str, pathlib.Path, io.IOBase or NoneType, default None
Tide model definition file for use
DEFINITION_FORMAT: str, default 'ascii'
Format for model definition file
- ``'ascii'``: tab-delimited definition file
- ``'json'``: JSON formatted definition file
CROP: bool, default False
Crop tide model data to (buffered) bounds
BOUNDS: list, np.ndarray or NoneType, default None
Boundaries for cropping tide model data
EPSG: int, default: 3031 (Polar Stereographic South, WGS84)
Input coordinate system
EPOCH: tuple, default (2000,1,1,0,0,0)
Expand Down Expand Up @@ -504,8 +531,8 @@ def tide_currents(

# get parameters for tide model
if DEFINITION_FILE is not None:
model = pyTMD.io.model(DIRECTORY).from_file(
pathlib.Path(DEFINITION_FILE).expanduser())
model = pyTMD.io.model(DIRECTORY).from_file(DEFINITION_FILE,

Check warning on line 534 in pyTMD/compute.py

View check run for this annotation

Codecov / codecov/patch

pyTMD/compute.py#L534

Added line #L534 was not covered by tests
format=DEFINITION_FORMAT)
else:
model = pyTMD.io.model(DIRECTORY, format=ATLAS_FORMAT,
compressed=GZIP).current(MODEL)
Expand Down Expand Up @@ -551,22 +578,22 @@ def tide_currents(
if model.format in ('OTIS', 'ATLAS', 'TMD3'):
amp,ph,D,c = pyTMD.io.OTIS.extract_constants(lon, lat, model.grid_file,
model.model_file['u'], model.projection, type=t,
method=METHOD, extrapolate=EXTRAPOLATE, cutoff=CUTOFF,
grid=model.format)
crop=CROP, bounds=BOUNDS, method=METHOD, extrapolate=EXTRAPOLATE,
cutoff=CUTOFF, grid=model.format)
# use delta time at 2000.0 to match TMD outputs
deltat = np.zeros((nt), dtype=np.float64)
elif (model.format == 'netcdf'):
amp,ph,D,c = pyTMD.io.ATLAS.extract_constants(lon, lat, model.grid_file,
model.model_file[t], type=t, method=METHOD,
extrapolate=EXTRAPOLATE, cutoff=CUTOFF, scale=model.scale,
compressed=model.compressed)
model.model_file[t], type=t, crop=CROP, bounds=BOUNDS,
method=METHOD, extrapolate=EXTRAPOLATE, cutoff=CUTOFF,
scale=model.scale, compressed=model.compressed)
# use delta time at 2000.0 to match TMD outputs
deltat = np.zeros((nt), dtype=np.float64)
elif (model.format == 'FES'):
amp,ph = pyTMD.io.FES.extract_constants(lon, lat, model.model_file[t],
type=t, version=model.version, method=METHOD,
extrapolate=EXTRAPOLATE, cutoff=CUTOFF, scale=model.scale,
compressed=model.compressed)
type=t, version=model.version, crop=CROP, bounds=BOUNDS,
method=METHOD, extrapolate=EXTRAPOLATE, cutoff=CUTOFF,
scale=model.scale, compressed=model.compressed)
# available model constituents
c = model.constituents
# delta time (TT - UT1)
Expand Down
2 changes: 2 additions & 0 deletions pyTMD/io/FES.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
UPDATE HISTORY:
Updated 07/2024: added new FES2022 to available known model versions
FES2022 have masked longitudes, only extract longitude data
FES2022 extrapolated data have zeroed out inland water bodies
added crop and bounds keywords for trimming model data
Updated 01/2024: attempt to extract constituent IDs from filenames
Updated 06/2023: extract ocean tide model variables for FES2012
Expand Down Expand Up @@ -725,6 +726,7 @@ def read_netcdf_file(
# calculate complex form of constituent oscillation
mask = (amp.data == amp.fill_value) | \
(ph.data == ph.fill_value) | \
((amp.data == 0) & (ph.data == 0)) | \
np.isnan(amp.data) | np.isnan(ph.data)
hc = np.ma.array(amp*np.exp(-1j*ph*np.pi/180.0), mask=mask,
fill_value=np.ma.default_fill_value(np.dtype(complex)))
Expand Down
4 changes: 2 additions & 2 deletions pyTMD/io/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1353,8 +1353,8 @@ def from_file(self,
format: str
format of the input definition file
- ``'ascii'`` for tab-delimited definition file
- ``'json'`` for JSON formatted definition file
- ``'ascii'``: tab-delimited definition file
- ``'json'``: JSON formatted definition file
"""
# Opening definition file and assigning file ID number
if isinstance(definition_file, io.IOBase):
Expand Down
9 changes: 8 additions & 1 deletion scripts/compute_tidal_currents.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
UPDATE HISTORY:
Updated 07/2024: assert that data type is a known value
added option to crop to the domain of the input data
added option to use JSON format definition files
Updated 06/2024: include attributes in output parquet files
Updated 05/2024: use function to reading parquet files to allow
reading and parsing of geometry column from geopandas datasets
Expand Down Expand Up @@ -200,6 +201,7 @@ def compute_tidal_currents(tide_dir, input_file, output_file,
ATLAS_FORMAT='netcdf',
GZIP=True,
DEFINITION_FILE=None,
DEFINITION_FORMAT='ascii',
CROP=False,
FORMAT='csv',
VARIABLES=[],
Expand All @@ -219,7 +221,8 @@ def compute_tidal_currents(tide_dir, input_file, output_file,

# get parameters for tide model
if DEFINITION_FILE is not None:
model = pyTMD.io.model(tide_dir).from_file(DEFINITION_FILE)
model = pyTMD.io.model(tide_dir).from_file(DEFINITION_FILE,
format=DEFINITION_FORMAT)
else:
model = pyTMD.io.model(tide_dir, format=ATLAS_FORMAT,
compressed=GZIP).current(TIDE_MODEL)
Expand Down Expand Up @@ -471,6 +474,9 @@ def arguments():
group.add_argument('--definition-file',
type=pathlib.Path,
help='Tide model definition file')
parser.add_argument('--definition-format',
type=str, default='ascii', choices=('ascii', 'json'),
help='Format for model definition file')
# crop tide model to (buffered) bounds of data
parser.add_argument('--crop', '-C',
default=False, action='store_true',
Expand Down Expand Up @@ -574,6 +580,7 @@ def main():
ATLAS_FORMAT=args.atlas_format,
GZIP=args.gzip,
DEFINITION_FILE=args.definition_file,
DEFINITION_FORMAT=args.definition_format,
CROP=args.crop,
FORMAT=args.format,
VARIABLES=args.variables,
Expand Down
9 changes: 8 additions & 1 deletion scripts/compute_tidal_elevations.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
UPDATE HISTORY:
Updated 07/2024: assert that data type is a known value
added option to crop to the domain of the input data
added option to use JSON format definition files
Updated 06/2024: include attributes in output parquet files
Updated 05/2024: use function to reading parquet files to allow
reading and parsing of geometry column from geopandas datasets
Expand Down Expand Up @@ -204,6 +205,7 @@ def compute_tidal_elevations(tide_dir, input_file, output_file,
ATLAS_FORMAT='netcdf',
GZIP=True,
DEFINITION_FILE=None,
DEFINITION_FORMAT='ascii',
CROP=False,
FORMAT='csv',
VARIABLES=[],
Expand All @@ -224,7 +226,8 @@ def compute_tidal_elevations(tide_dir, input_file, output_file,

# get parameters for tide model
if DEFINITION_FILE is not None:
model = pyTMD.io.model(tide_dir).from_file(DEFINITION_FILE)
model = pyTMD.io.model(tide_dir).from_file(DEFINITION_FILE,
format=DEFINITION_FORMAT)
else:
model = pyTMD.io.model(tide_dir, format=ATLAS_FORMAT,
compressed=GZIP).elevation(TIDE_MODEL)
Expand Down Expand Up @@ -467,6 +470,9 @@ def arguments():
group.add_argument('--definition-file',
type=pathlib.Path,
help='Tide model definition file')
parser.add_argument('--definition-format',
type=str, default='ascii', choices=('ascii', 'json'),
help='Format for model definition file')
# crop tide model to (buffered) bounds of data
parser.add_argument('--crop', '-C',
default=False, action='store_true',
Expand Down Expand Up @@ -575,6 +581,7 @@ def main():
ATLAS_FORMAT=args.atlas_format,
GZIP=args.gzip,
DEFINITION_FILE=args.definition_file,
DEFINITION_FORMAT=args.definition_format,
CROP=args.crop,
FORMAT=args.format,
VARIABLES=args.variables,
Expand Down
9 changes: 9 additions & 0 deletions test/model_FES2022b_extrapolated.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
format FES
name FES2022
model_file fes2022b/ocean_tide_extrapolated/*fes2022.nc*
type z
version FES2022
variable tide_ocean
scale 0.01
compressed True
reference https://doi.org/10.24400/527896/A01-2024.004
1 change: 1 addition & 0 deletions test/model_FES2022b_extrapolated.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"format": "FES", "name": "FES2022", "model_file": "fes2022b/ocean_tide_extrapolated/*fes2022.nc*", "type": "z", "version": "FES2022", "variable": "tide_ocean", "scale": 0.01, "compressed": true, "reference": "https://doi.org/10.24400/527896/A01-2024.004"}

0 comments on commit 2a16ea7

Please sign in to comment.