diff --git a/doc/source/api_reference/check_points.rst b/doc/source/api_reference/check_points.rst index d7c57b91..81bec012 100644 --- a/doc/source/api_reference/check_points.rst +++ b/doc/source/api_reference/check_points.rst @@ -3,7 +3,7 @@ check_points ============ - Check if points are within a tide model domain -- Can check OTIS format tidal solutions provided by Ohio State University and ESR +- Can check OTIS format tidal solutions provided by Oregon State University and ESR - Can check Global Tide Model (GOT) solutions provided by Richard Ray at GSFC - Can check Finite Element Solution (FES) models provided by AVISO diff --git a/doc/source/api_reference/compute.rst b/doc/source/api_reference/compute.rst index f5df85a2..b677674b 100644 --- a/doc/source/api_reference/compute.rst +++ b/doc/source/api_reference/compute.rst @@ -4,12 +4,12 @@ compute - Calculates tidal elevations at points and times - * Can use OTIS format tidal solutions provided by Ohio State University and ESR + * Can use OTIS format tidal solutions provided by Oregon State University and ESR * Can use Global Tide Model (GOT) solutions provided by Richard Ray at GSFC * Can use Finite Element Solution (FES) models provided by AVISO - Calculates tidal currents at points and times - * Can use OTIS format tidal solutions provided by Ohio State University and ESR + * Can use OTIS format tidal solutions provided by Oregon State University and ESR * Can use Finite Element Solution (FES) models provided by AVISO - Calculates long-period equilibrium tides (LPET) at points and times diff --git a/doc/source/api_reference/compute_tidal_currents.rst b/doc/source/api_reference/compute_tidal_currents.rst index f8e64180..f83ba135 100644 --- a/doc/source/api_reference/compute_tidal_currents.rst +++ b/doc/source/api_reference/compute_tidal_currents.rst @@ -3,7 +3,7 @@ compute_tidal_currents.py ========================= - Calculates tidal currents for an input file following [Egbert2002]_ -- Can use OTIS format tidal solutions provided by Ohio State University and ESR +- Can use OTIS format tidal solutions provided by Oregon State University and ESR - Can use Finite Element Solution (FES) models provided by AVISO - Can read and write ascii, netCDF4, HDF5, parquet and geotiff formats diff --git a/doc/source/api_reference/compute_tidal_elevations.rst b/doc/source/api_reference/compute_tidal_elevations.rst index a1f87185..e4c5cde0 100644 --- a/doc/source/api_reference/compute_tidal_elevations.rst +++ b/doc/source/api_reference/compute_tidal_elevations.rst @@ -3,7 +3,7 @@ compute_tidal_elevations.py =========================== - Calculates tidal elevations for an input file following [Egbert2002]_ -- Can use OTIS format tidal solutions provided by Ohio State University and ESR +- Can use OTIS format tidal solutions provided by Oregon State University and ESR - Can use Global Tide Model (GOT) solutions provided by Richard Ray at GSFC - Can use Finite Element Solution (FES) models provided by AVISO - Can read and write ascii, netCDF4, HDF5, parquet and geotiff formats diff --git a/doc/source/api_reference/io/ATLAS.rst b/doc/source/api_reference/io/ATLAS.rst index 92496c23..b2b31be1 100644 --- a/doc/source/api_reference/io/ATLAS.rst +++ b/doc/source/api_reference/io/ATLAS.rst @@ -2,7 +2,7 @@ ATLAS ===== -- Reads netCDF format tidal solutions provided by Ohio State University and ESR +- Reads netCDF format tidal solutions provided by Oregon State University and ESR - Spatially interpolates tidal constituents to input coordinates Calling Sequence diff --git a/doc/source/api_reference/io/GOT.rst b/doc/source/api_reference/io/GOT.rst index 64ae94bf..2815611d 100644 --- a/doc/source/api_reference/io/GOT.rst +++ b/doc/source/api_reference/io/GOT.rst @@ -3,6 +3,9 @@ GOT === - Reads files for Richard Ray's Global Ocean Tide (GOT) models + + * ascii format + * netcdf format - Spatially interpolates tidal constituents to input coordinates Calling Sequence diff --git a/doc/source/api_reference/io/OTIS.rst b/doc/source/api_reference/io/OTIS.rst index f0f0cafd..ec1a8db7 100644 --- a/doc/source/api_reference/io/OTIS.rst +++ b/doc/source/api_reference/io/OTIS.rst @@ -2,7 +2,7 @@ OTIS ==== -- Reads OTIS format tidal solutions provided by Ohio State University and ESR +- Reads OTIS format tidal solutions provided by Oregon State University and ESR * multi-constituent binary * ATLAS-compact binary diff --git a/doc/source/api_reference/reduce_OTIS_files.rst b/doc/source/api_reference/reduce_OTIS_files.rst index 399aeac1..af7ab349 100644 --- a/doc/source/api_reference/reduce_OTIS_files.rst +++ b/doc/source/api_reference/reduce_OTIS_files.rst @@ -2,7 +2,7 @@ reduce_OTIS_files.py ==================== -- Reduces OTIS-format tidal files provided by Ohio State University and ESR to a regional subset +- Reduces OTIS-format tidal files provided by Oregon State University and ESR to a regional subset `Source code`__ diff --git a/doc/source/getting_started/Getting-Started.rst b/doc/source/getting_started/Getting-Started.rst index f96cc035..6cc831bf 100644 --- a/doc/source/getting_started/Getting-Started.rst +++ b/doc/source/getting_started/Getting-Started.rst @@ -146,38 +146,38 @@ Each definition file regardless of the format should have ``name``, ``format`` a Each model type also requires specific sets of parameters for the model reader. For models with multiple constituent files, the files can be found using a ``glob`` string to search a directory. -- ``OTIS``, ``ATLAS`` and ``TMD3`` +- ``OTIS``, ``ATLAS-compact`` and ``TMD3`` - * ``format``: ``OTIS``, ``ATLAS`` or ``TMD3`` + * ``format``: ``OTIS``, ``ATLAS-compact`` or ``TMD3`` * ``grid_file``: path to model grid file * ``model_file``: path to model constituent file(s) or a ``glob`` string * ``name``: tide model name * ``projection``: `model spatial projection <./Getting-Started.html#spatial-coordinates>`_. * ``type``: ``z`` or ``u,v`` -- ``netcdf`` +- ``ATLAS-netcdf`` * ``compressed``: model files are gzip compressed - * ``format``: ``netcdf`` + * ``format``: ``ATLAS-netcdf`` * ``grid_file``: path to model grid file * ``model_file``: path to model constituent files or a ``glob`` string * ``name``: tide model name * ``scale``: scaling factor for converting to output units * ``type``: ``z`` or ``u,v`` -- ``GOT`` +- ``GOT-ascii`` and ``GOT-netcdf`` * ``compressed``: model files are gzip compressed - * ``format``: ``GOT`` + * ``format``: ``GOT-ascii`` or ``GOT-netcdf`` * ``model_file``: path to model constituent files or a ``glob`` string * ``name``: tide model name * ``scale``: scaling factor for converting to output units * ``type``: ``z`` -- ``FES`` +- ``FES-ascii`` and ``FES-netcdf`` * ``compressed``: model files are gzip compressed - * ``format``: ``FES`` + * ``format``: ``FES-ascii`` or ``FES-netcdf`` * ``model_file``: path to model constituent files or a ``glob`` string * ``name``: tide model name * ``scale``: scaling factor for converting to output units diff --git a/notebooks/Check Tide Map.ipynb b/notebooks/Check Tide Map.ipynb index 58484fec..ce62e5da 100644 --- a/notebooks/Check Tide Map.ipynb +++ b/notebooks/Check Tide Map.ipynb @@ -10,7 +10,7 @@ "\n", "Check if a given point is within a tide model domain\n", "\n", - "OTIS format tidal solutions provided by Ohio State University and ESR \n", + "OTIS format tidal solutions provided by Oregon State University and ESR \n", "- http://volkov.oce.orst.edu/tides/region.html \n", "- https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/\n", "- ftp://ftp.esr.org/pub/datasets/tmd/ \n", @@ -116,22 +116,28 @@ " ).elevation(TMDwidgets.model.value)\n", " \n", "# read tidal constants and interpolate to grid points\n", - "if model.format in ('OTIS','ATLAS','TMD3'):\n", + "if model.format in ('OTIS','ATLAS-compact','TMD3'):\n", " # if reading a single OTIS solution\n", " xi,yi,hz,mz,iob,dt = pyTMD.io.OTIS.read_otis_grid(model.grid_file)\n", - "elif (model.format == 'netcdf'):\n", + "elif model.format in ('ATLAS-netcdf',):\n", " # if reading a netCDF OTIS atlas solution\n", " xi,yi,hz = pyTMD.io.ATLAS.read_netcdf_grid(model.grid_file,\n", " compressed=model.compressed, type='z')\n", " # invert bathymetry mask\n", " mz = np.invert(hz.mask)\n", - "elif (model.format == 'GOT'):\n", + "elif (model.format == 'GOT-ascii'):\n", " # if reading a NASA GOT solution\n", " hc,xi,yi,c = pyTMD.io.GOT.read_ascii_file(model.model_file[0],\n", " compressed=model.compressed)\n", " # invert tidal constituent mask\n", " mz = np.invert(hc.mask)\n", - "elif (model.format == 'FES'):\n", + "elif (model.format == 'GOT-netcdf'):\n", + " # if reading a NASA GOT netcdf solution\n", + " hc,xi,yi,c = pyTMD.io.GOT.read_netcdf_file(model.model_file[0],\n", + " compressed=model.compressed)\n", + " # invert tidal constituent mask\n", + " mz = np.invert(hc.mask)\n", + "elif (model.format == 'FES-netcdf'):\n", " # if reading a FES netCDF solution\n", " hc,xi,yi = pyTMD.io.FES.read_netcdf_file(model.model_file[0],\n", " compressed=model.compressed, type='z', version=model.version)\n", @@ -154,7 +160,7 @@ " LON = np.atleast_1d(LON)\n", " LAT = np.atleast_1d(LAT)\n", " # read tidal constants and interpolate to grid points\n", - " if model.format in ('OTIS','ATLAS','TMD3'):\n", + " if model.format in ('OTIS','ATLAS-compact','TMD3'):\n", " # if reading a single OTIS solution\n", " xi,yi,hz,mz,iob,dt = pyTMD.io.OTIS.read_otis_grid(model.grid_file)\n", " # convert coordinate systems of input latitude and longitude\n", @@ -168,21 +174,21 @@ " if (np.max(x) > np.max(xi)) & (model.projection == '4326'):\n", " gt180, = np.nonzero(x > 180)\n", " x[gt180] -= 360.0\n", - " elif (model.format == 'netcdf'):\n", + " elif (model.format == 'ATLAS-netcdf'):\n", " # if reading a netCDF OTIS atlas solution\n", " # adjust longitudinal convention of input latitude and longitude\n", " # to fit tide model convention\n", " x,y = np.copy([LON,LAT]).astype(np.float64)\n", " lt0, = np.nonzero(x < 0)\n", " x[lt0] += 360.0\n", - " elif (model.format == 'GOT'):\n", + " elif model.format in ('GOT-ascii', 'GOT-netcdf'):\n", " # if reading a NASA GOT solution\n", " # adjust longitudinal convention of input latitude and longitude\n", " # to fit tide model convention\n", " x,y = np.copy([LON,LAT]).astype(np.float64)\n", " lt0, = np.nonzero(x < 0)\n", " x[lt0] += 360.0\n", - " elif (model.format == 'FES'):\n", + " elif (model.format == 'FES-netcdf'):\n", " # if reading a FES netCDF solution\n", " # adjust longitudinal convention of input latitude and longitude\n", " # to fit tide model convention\n", diff --git a/notebooks/Plot ATLAS Compact.ipynb b/notebooks/Plot ATLAS Compact.ipynb index 40076b38..b84fa346 100644 --- a/notebooks/Plot ATLAS Compact.ipynb +++ b/notebooks/Plot ATLAS Compact.ipynb @@ -10,7 +10,7 @@ "\n", "Check if a given point is within a tide model domain\n", "\n", - "OTIS format tidal solutions provided by Ohio State University and ESR \n", + "OTIS format tidal solutions provided by Oregon State University and ESR \n", "- http://volkov.oce.orst.edu/tides/region.html \n", "\n", "#### Python Dependencies\n", diff --git a/notebooks/Plot Antarctic Tidal Currents.ipynb b/notebooks/Plot Antarctic Tidal Currents.ipynb index 467df40b..fe91db60 100644 --- a/notebooks/Plot Antarctic Tidal Currents.ipynb +++ b/notebooks/Plot Antarctic Tidal Currents.ipynb @@ -10,7 +10,7 @@ "\n", "Demonstrates plotting hourly tidal currents around Antarctica\n", "\n", - "OTIS format tidal solutions provided by Ohio State University and ESR \n", + "OTIS format tidal solutions provided by Oregon State University and ESR \n", "- http://volkov.oce.orst.edu/tides/region.html \n", "- https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/\n", "- ftp://ftp.esr.org/pub/datasets/tmd/ \n", @@ -185,23 +185,23 @@ "# iterate over u and v currents\n", "for TYPE in model.type:\n", " # read tidal constants and interpolate to grid points\n", - " if model.format in ('OTIS','ATLAS','TMD3'):\n", + " if model.format in ('OTIS','ATLAS-compact','TMD3'):\n", " amp,ph,D,c = pyTMD.io.OTIS.extract_constants(lon, lat, model.grid_file,\n", " model.model_file['u'], model.projection, type=TYPE, crop=True,\n", - " method='spline', grid=model.format)\n", + " method='spline', grid=corrections)\n", " DELTAT = np.zeros_like(ts.tide)\n", - " elif (model.format == 'netcdf'):\n", + " elif (model.format == 'ATLAS-netcdf'):\n", " amp,ph,D,c = pyTMD.io.ATLAS.extract_constants(lon, lat, model.grid_file,\n", " model.model_file[TYPE], type=TYPE, crop=True, method='spline',\n", " scale=model.scale, compressed=model.compressed)\n", " DELTAT = np.zeros_like(ts.tide)\n", - " elif (model.format == 'GOT'):\n", + " elif model.format in ('GOT-ascii', 'GOT-netcdf'):\n", " amp,ph,c = pyTMD.io.GOT.extract_constants(lon, lat, model.model_file[TYPE],\n", " crop=True, method='spline', scale=model.scale,\n", " compressed=model.compressed)\n", " # delta time (TT - UT1)\n", " DELTAT = ts.tt_ut1\n", - " elif (model.format == 'FES'):\n", + " elif (model.format == 'FES-netcdf'):\n", " amp,ph = pyTMD.io.FES.extract_constants(lon, lat, model.model_file[TYPE],\n", " type=TYPE, version=model.version, crop=True, method='spline',\n", " scale=model.scale, compressed=model.compressed)\n", @@ -219,9 +219,9 @@ " for hour in range(24):\n", " # predict tidal elevations at time and infer minor corrections\n", " TIDE = pyTMD.predict.map(ts.tide[hour], hc, c, deltat=DELTAT[hour],\n", - " corrections=model.format)\n", + " corrections=corrections)\n", " MINOR = pyTMD.predict.infer_minor(ts.tide[hour], hc, c,\n", - " deltat=DELTAT[hour], corrections=model.format)\n", + " deltat=DELTAT[hour], corrections=corrections)\n", " # add major and minor components and reform grid\n", " tide[TYPE][:,:,hour] = np.reshape((TIDE+MINOR),(ny,nx))" ] diff --git a/notebooks/Plot Antarctic Tide Range.ipynb b/notebooks/Plot Antarctic Tide Range.ipynb index 6839ecd2..1f40fd9f 100644 --- a/notebooks/Plot Antarctic Tide Range.ipynb +++ b/notebooks/Plot Antarctic Tide Range.ipynb @@ -10,7 +10,7 @@ "\n", "Demonstrates plotting the tidal amplitudes around Antarctica\n", "\n", - "OTIS format tidal solutions provided by Ohio State University and ESR \n", + "OTIS format tidal solutions provided by Oregon State University and ESR \n", "- http://volkov.oce.orst.edu/tides/region.html \n", "- https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/\n", "- ftp://ftp.esr.org/pub/datasets/tmd/ \n", @@ -219,19 +219,19 @@ "outputs": [], "source": [ "# read tidal constants and interpolate to grid points\n", - "if model.format in ('OTIS','ATLAS','TMD3'):\n", + "if model.format in ('OTIS','ATLAS-compact','TMD3'):\n", " amp,ph,D,c = pyTMD.io.OTIS.extract_constants(lon, lat, model.grid_file,\n", " model.model_file, model.projection, type=model.type, crop=True,\n", - " method='spline', grid=model.format)\n", - "elif (model.format == 'netcdf'):\n", + " method='spline', grid=corrections)\n", + "elif (model.format == 'ATLAS-netcdf'):\n", " amp,ph,D,c = pyTMD.io.ATLAS.extract_constants(lon, lat, model.grid_file,\n", " model.model_file, type=model.type, crop=True, method='spline',\n", " scale=model.scale, compressed=model.compressed)\n", - "elif (model.format == 'GOT'):\n", + "elif model.format in ('GOT-ascii', 'GOT-netcdf'):\n", " amp,ph,c = pyTMD.io.GOT.extract_constants(lon, lat, model.model_file,\n", " crop=True, method='spline', scale=model.scale,\n", " compressed=model.compressed)\n", - "elif (model.format == 'FES'):\n", + "elif (model.format == 'FES-netcdf'):\n", " amp,ph = pyTMD.io.FES.extract_constants(lon, lat, model.model_file,\n", " type=model.type, version=model.version, crop=True,\n", " method='spline', scale=model.scale, compressed=model.compressed)\n", @@ -319,7 +319,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.10.14" }, "vscode": { "interpreter": { diff --git a/notebooks/Plot Arctic Ocean Map.ipynb b/notebooks/Plot Arctic Ocean Map.ipynb index 10256eb5..81776bc1 100644 --- a/notebooks/Plot Arctic Ocean Map.ipynb +++ b/notebooks/Plot Arctic Ocean Map.ipynb @@ -10,7 +10,7 @@ "\n", "Demonstrates plotting hourly tidal displacements for the Arctic Ocean\n", "\n", - "OTIS format tidal solutions provided by Ohio State University and ESR \n", + "OTIS format tidal solutions provided by Oregon State University and ESR \n", "- http://volkov.oce.orst.edu/tides/region.html \n", "- https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/\n", "- ftp://ftp.esr.org/pub/datasets/tmd/ \n", @@ -183,23 +183,23 @@ " YMD.day, hour=np.arange(24))\n", "\n", "# read tidal constants and interpolate to grid points\n", - "if model.format in ('OTIS','ATLAS','TMD3'):\n", + "if model.format in ('OTIS','ATLAS-compact','TMD3'):\n", " amp,ph,D,c = pyTMD.io.OTIS.extract_constants(lon, lat, model.grid_file,\n", " model.model_file, model.projection, type=model.type, crop=True,\n", - " method='spline', grid=model.format)\n", + " method='spline', grid=corrections)\n", " DELTAT = np.zeros_like(ts.tide)\n", - "elif (model.format == 'netcdf'):\n", + "elif (model.format == 'ATLAS-netcdf'):\n", " amp,ph,D,c = pyTMD.io.ATLAS.extract_constants(lon, lat, model.grid_file,\n", " model.model_file, type=model.type, crop=True, method='spline',\n", " scale=model.scale, compressed=model.compressed)\n", " DELTAT = np.zeros_like(ts.tide)\n", - "elif (model.format == 'GOT'):\n", + "elif model.format in ('GOT-ascii', 'GOT-netcdf'):\n", " amp,ph,c = pyTMD.io.GOT.extract_constants(lon, lat, model.model_file,\n", " crop=True, method='spline', scale=model.scale,\n", " compressed=model.compressed)\n", " # delta time (TT - UT1)\n", " DELTAT = ts.tt_ut1\n", - "elif (model.format == 'FES'):\n", + "elif (model.format == 'FES-netcdf'):\n", " amp,ph = pyTMD.io.FES.extract_constants(lon, lat, model.model_file,\n", " type=model.type, version=model.version, crop=True,\n", " method='spline', scale=model.scale, compressed=model.compressed)\n", @@ -217,9 +217,9 @@ "for hour in range(24):\n", " # predict tidal elevations at time and infer minor corrections\n", " TIDE = pyTMD.predict.map(ts.tide[hour], hc, c, deltat=DELTAT[hour],\n", - " corrections=model.format)\n", + " corrections=corrections)\n", " MINOR = pyTMD.predict.infer_minor(ts.tide[hour], hc, c,\n", - " deltat=DELTAT[hour], corrections=model.format)\n", + " deltat=DELTAT[hour], corrections=corrections)\n", " # add major and minor components and reform grid\n", " # convert from meters to centimeters\n", " tide_cm[:,:,hour] = 100.0*np.reshape((TIDE+MINOR),(ny,nx))" diff --git a/notebooks/Plot Ross Ice Shelf Map.ipynb b/notebooks/Plot Ross Ice Shelf Map.ipynb index 718624f2..d2ad0a18 100644 --- a/notebooks/Plot Ross Ice Shelf Map.ipynb +++ b/notebooks/Plot Ross Ice Shelf Map.ipynb @@ -10,7 +10,7 @@ "\n", "Demonstrates plotting hourly tidal displacements for the Ross Ice Shelf\n", "\n", - "OTIS format tidal solutions provided by Ohio State University and ESR \n", + "OTIS format tidal solutions provided by Oregon State University and ESR \n", "- http://volkov.oce.orst.edu/tides/region.html \n", "- https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/\n", "- ftp://ftp.esr.org/pub/datasets/tmd/ \n", @@ -183,23 +183,23 @@ " YMD.day, hour=np.arange(24))\n", "\n", "# read tidal constants and interpolate to grid points\n", - "if model.format in ('OTIS','ATLAS','TMD3'):\n", + "if model.format in ('OTIS','ATLAS-compact','TMD3'):\n", " amp,ph,D,c = pyTMD.io.OTIS.extract_constants(lon, lat, model.grid_file,\n", " model.model_file, model.projection, type=model.type, crop=True,\n", - " method='spline', grid=model.format)\n", + " method='spline', grid=corrections)\n", " DELTAT = np.zeros_like(ts.tide)\n", - "elif (model.format == 'netcdf'):\n", + "elif (model.format == 'ATLAS-netcdf'):\n", " amp,ph,D,c = pyTMD.io.ATLAS.extract_constants(lon, lat, model.grid_file,\n", " model.model_file, type=model.type, crop=True, method='spline',\n", " scale=model.scale, compressed=model.compressed)\n", " DELTAT = np.zeros_like(ts.tide)\n", - "elif (model.format == 'GOT'):\n", + "elif model.format in ('GOT-ascii', 'GOT-netcdf'):\n", " amp,ph,c = pyTMD.io.GOT.extract_constants(lon, lat, model.model_file,\n", " crop=True, method='spline', scale=model.scale,\n", " compressed=model.compressed)\n", " # delta time (TT - UT1)\n", " DELTAT = ts.tt_ut1\n", - "elif (model.format == 'FES'):\n", + "elif (model.format == 'FES-netcdf'):\n", " amp,ph = pyTMD.io.FES.extract_constants(lon, lat, model.model_file,\n", " type=model.type, version=model.version, crop=True,\n", " method='spline', scale=model.scale, compressed=model.compressed)\n", @@ -217,9 +217,9 @@ "for hour in range(24):\n", " # predict tidal elevations at time and infer minor corrections\n", " TIDE = pyTMD.predict.map(ts.tide[hour], hc, c, deltat=DELTAT[hour],\n", - " corrections=model.format)\n", + " corrections=corrections)\n", " MINOR = pyTMD.predict.infer_minor(ts.tide[hour], hc, c,\n", - " deltat=DELTAT[hour], corrections=model.format)\n", + " deltat=DELTAT[hour], corrections=corrections)\n", " # add major and minor components and reform grid\n", " # convert from meters to centimeters\n", " tide_cm[:,:,hour] = 100.0*np.reshape((TIDE+MINOR),(ny,nx))" diff --git a/notebooks/Plot Tide Forecasts.ipynb b/notebooks/Plot Tide Forecasts.ipynb index dfd0faf0..40721d6d 100644 --- a/notebooks/Plot Tide Forecasts.ipynb +++ b/notebooks/Plot Tide Forecasts.ipynb @@ -10,7 +10,7 @@ "\n", "Plots the daily tidal displacements for a given location\n", "\n", - "OTIS format tidal solutions provided by Ohio State University and ESR \n", + "OTIS format tidal solutions provided by Oregon State University and ESR \n", "- http://volkov.oce.orst.edu/tides/region.html \n", "- https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/\n", "- ftp://ftp.esr.org/pub/datasets/tmd/ \n", @@ -156,26 +156,26 @@ "delta_file = pyTMD.utilities.get_data_path(['data','merged_deltat.data'])\n", "\n", "# read tidal constants and interpolate to leaflet points\n", - "if model.format in ('OTIS','ATLAS','TMD3'):\n", + "if model.format in ('OTIS','ATLAS-compact','TMD3'):\n", " constituents = pyTMD.io.OTIS.read_constants(\n", " model.grid_file, model.model_file,\n", " model.projection, type=model.type,\n", - " grid=model.format)\n", + " grid=corrections)\n", " c = constituents.fields\n", " DELTAT = np.zeros_like(ts.tide)\n", - "elif (model.format == 'netcdf'):\n", + "elif (model.format == 'ATLAS-netcdf'):\n", " constituents = pyTMD.io.ATLAS.read_constants(\n", " model.grid_file, model.model_file,\n", " type=model.type, compressed=model.compressed)\n", " c = constituents.fields\n", " DELTAT = np.zeros_like(ts.tide)\n", - "elif (model.format == 'GOT'):\n", + "elif model.format in ('GOT-ascii', 'GOT-netcdf'):\n", " constituents = pyTMD.io.GOT.read_constants(\n", " model.model_file, compressed=model.compressed)\n", " c = constituents.fields\n", " # delta time (TT - UT1)\n", " DELTAT = ts.tt_ut1\n", - "elif (model.format == 'FES'):\n", + "elif (model.format == 'FES-netcdf'):\n", " constituents = pyTMD.io.FES.read_constants(model.model_file,\n", " type=model.type, version=model.version,\n", " compressed=model.compressed)\n", @@ -189,22 +189,22 @@ " LAT,LON = np.copy(m.marker.location)\n", " # verify longitudes\n", " LON = m.wrap_longitudes(LON)\n", - " if model.format in ('OTIS','ATLAS','TMD3'):\n", + " if model.format in ('OTIS','ATLAS-compact','TMD3'):\n", " amp,ph,D = pyTMD.io.OTIS.interpolate_constants(\n", " np.atleast_1d(LON), np.atleast_1d(LAT),\n", " constituents, model.projection, type=model.type,\n", " method='spline', extrapolate=True)\n", - " elif (model.format == 'netcdf'):\n", + " elif (model.format == 'ATLAS-netcdf'):\n", " amp,ph,D = pyTMD.io.ATLAS.interpolate_constants(\n", " np.atleast_1d(LON), np.atleast_1d(LAT),\n", " constituents, type=model.type, scale=model.scale,\n", " method='spline', extrapolate=True)\n", - " elif (model.format == 'GOT'):\n", + " elif model.format in ('GOT-ascii', 'GOT-netcdf'):\n", " amp,ph = pyTMD.io.GOT.interpolate_constants(\n", " np.atleast_1d(LON), np.atleast_1d(LAT),\n", " constituents, scale=model.scale,\n", " method='spline', extrapolate=True)\n", - " elif (model.format == 'FES'):\n", + " elif (model.format == 'FES-netcdf'):\n", " amp,ph = pyTMD.io.FES.interpolate_constants(\n", " np.atleast_1d(LON), np.atleast_1d(LAT),\n", " constituents, scale=model.scale,\n", @@ -215,9 +215,9 @@ " hc = amp*np.exp(cph)\n", " # predict tidal elevations at time and infer minor corrections\n", " TIDE = pyTMD.predict.time_series(ts.tide, hc, c,\n", - " deltat=DELTAT, corrections=model.format)\n", + " deltat=DELTAT, corrections=corrections)\n", " MINOR = pyTMD.predict.infer_minor(ts.tide, hc, c,\n", - " deltat=DELTAT, corrections=model.format)\n", + " deltat=DELTAT, corrections=corrections)\n", " TIDE.data[:] += MINOR.data[:]\n", " # convert to centimeters\n", " TIDE.data[:] *= 100.0\n", diff --git a/notebooks/Solve Synthetic Tides.ipynb b/notebooks/Solve Synthetic Tides.ipynb index 9e9b0600..e1ba0781 100644 --- a/notebooks/Solve Synthetic Tides.ipynb +++ b/notebooks/Solve Synthetic Tides.ipynb @@ -139,26 +139,26 @@ "ts = timescale.time.Timescale().from_calendar(2000, 1, 1, minute=minutes)\n", "\n", "# read tidal constants and interpolate to leaflet points\n", - "if model.format in ('OTIS','ATLAS','TMD3'):\n", + "if model.format in ('OTIS','ATLAS-compact','TMD3'):\n", " constituents = pyTMD.io.OTIS.read_constants(\n", " model.grid_file, model.model_file,\n", " model.projection, type=model.type,\n", - " grid=model.format)\n", + " grid=corrections)\n", " c = constituents.fields\n", " DELTAT = np.zeros_like(ts.tide)\n", - "elif (model.format == 'netcdf'):\n", + "elif (model.format == 'ATLAS-netcdf'):\n", " constituents = pyTMD.io.ATLAS.read_constants(\n", " model.grid_file, model.model_file,\n", " type=model.type, compressed=model.compressed)\n", " c = constituents.fields\n", " DELTAT = np.zeros_like(ts.tide)\n", - "elif (model.format == 'GOT'):\n", + "elif model.format in ('GOT-ascii', 'GOT-netcdf'):\n", " constituents = pyTMD.io.GOT.read_constants(\n", " model.model_file, compressed=model.compressed)\n", " c = constituents.fields\n", " # delta time (TT - UT1)\n", " DELTAT = ts.tt_ut1\n", - "elif (model.format == 'FES'):\n", + "elif (model.format == 'FES-netcdf'):\n", " constituents = pyTMD.io.FES.read_constants(model.model_file,\n", " type=model.type, version=model.version,\n", " compressed=model.compressed)\n", @@ -172,22 +172,22 @@ " LAT,LON = np.copy(m.marker.location)\n", " # verify longitudes\n", " LON = m.wrap_longitudes(LON)\n", - " if model.format in ('OTIS','ATLAS','TMD3'):\n", + " if model.format in ('OTIS','ATLAS-compact','TMD3'):\n", " amp,ph,D = pyTMD.io.OTIS.interpolate_constants(\n", " np.atleast_1d(LON), np.atleast_1d(LAT),\n", " constituents, model.projection, type=model.type,\n", " method='spline', extrapolate=True)\n", - " elif (model.format == 'netcdf'):\n", + " elif (model.format == 'ATLAS-netcdf'):\n", " amp,ph,D = pyTMD.io.ATLAS.interpolate_constants(\n", " np.atleast_1d(LON), np.atleast_1d(LAT),\n", " constituents, type=model.type, scale=model.scale,\n", " method='spline', extrapolate=True)\n", - " elif (model.format == 'GOT'):\n", + " elif model.format in ('GOT-ascii', 'GOT-netcdf'):\n", " amp,ph = pyTMD.io.GOT.interpolate_constants(\n", " np.atleast_1d(LON), np.atleast_1d(LAT),\n", " constituents, scale=model.scale,\n", " method='spline', extrapolate=True)\n", - " elif (model.format == 'FES'):\n", + " elif (model.format == 'FES-netcdf'):\n", " amp,ph = pyTMD.io.FES.interpolate_constants(\n", " np.atleast_1d(LON), np.atleast_1d(LAT),\n", " constituents, scale=model.scale,\n", @@ -198,14 +198,14 @@ " hc = amp*np.exp(cph)\n", " # predict tidal elevations at time 1 and infer minor corrections\n", " TIDE = pyTMD.predict.time_series(ts.tide, hc, c,\n", - " deltat=DELTAT, corrections=model.format)\n", + " deltat=DELTAT, corrections=corrections)\n", " MINOR = pyTMD.predict.infer_minor(ts.tide, hc, c,\n", - " deltat=DELTAT, corrections=model.format)\n", + " deltat=DELTAT, corrections=corrections)\n", " TIDE.data[:] += MINOR.data[:]\n", "\n", " # solve for harmonic constants\n", " famp, fph = pyTMD.solve.constants(ts.tide, TIDE.data, c,\n", - " deltat=DELTAT, corrections=model.format)\n", + " deltat=DELTAT, corrections=corrections)\n", "\n", " # create a HTML table with values\n", " # HTML table header\n", diff --git a/pyTMD/check_points.py b/pyTMD/check_points.py index b5e23040..00c11681 100644 --- a/pyTMD/check_points.py +++ b/pyTMD/check_points.py @@ -1,10 +1,10 @@ #!/usr/bin/env python u""" check_points.py -Written by Tyler Sutterley (04/2024) +Written by Tyler Sutterley (07/2024) Check if points are within a tide model domain -OTIS format tidal solutions provided by Ohio State University and ESR +OTIS format tidal solutions provided by Oregon State University and ESR http://volkov.oce.orst.edu/tides/region.html https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/ ftp://ftp.esr.org/pub/datasets/tmd/ @@ -18,7 +18,7 @@ OPTIONS: DIRECTORY: working data directory for tide models MODEL: Tide model to use - ATLAS_FORMAT: ATLAS tide model format (OTIS, netcdf) + ATLAS_FORMAT: ATLAS tide model format (OTIS, ATLAS-netcdf) GZIP: Tide model files are gzip compressed DEFINITION_FILE: Tide model definition file for use EPSG: input coordinate system @@ -52,6 +52,10 @@ interpolate.py: interpolation routines for spatial data UPDATE HISTORY: + Updated 07/2024: renamed format for ATLAS to ATLAS-compact + renamed format for netcdf to ATLAS-netcdf + renamed format for FES to FES-netcdf and added FES-ascii + renamed format for GOT to GOT-ascii and added GOT-netcdf Updated 04/2024: use wrapper to importlib for optional dependencies Updated 12/2023: use new crs class for coordinate reprojection Updated 08/2023: changed ESR netCDF4 format to TMD3 format @@ -87,7 +91,7 @@ def check_points(x: np.ndarray, y: np.ndarray, DIRECTORY: str | pathlib.Path | None = None, MODEL: str | None = None, - ATLAS_FORMAT: str = 'netcdf', + ATLAS_FORMAT: str = 'ATLAS-netcdf', GZIP: bool = False, DEFINITION_FILE: str | pathlib.Path | None = None, EPSG: str | int = 3031, @@ -106,11 +110,8 @@ def check_points(x: np.ndarray, y: np.ndarray, working data directory for tide models MODEL: str or NoneType, default None Tide model to use - ATLAS_FORMAT: str, default 'netcdf' + ATLAS_FORMAT: str, default 'ATLAS-netcdf' ATLAS tide model format - - - ``'OTIS'`` - - ``'netcdf'`` GZIP: bool, default False Tide model files are gzip compressed DEFINITION_FILE: str or NoneType, default None @@ -155,7 +156,7 @@ def check_points(x: np.ndarray, y: np.ndarray, ) # read tidal constants and interpolate to grid points - if model.format in ('OTIS','ATLAS','TMD3'): + if model.format in ('OTIS','ATLAS-compact','TMD3'): # if reading a single OTIS solution xi, yi, hz, mz, iob, dt = pyTMD.io.OTIS.read_otis_grid( pathlib.Path(model.grid_file).expanduser()) @@ -164,7 +165,7 @@ def check_points(x: np.ndarray, y: np.ndarray, # adjust dimensions of input coordinates to be iterable # run wrapper function to convert coordinate systems of input lat/lon X, Y = pyTMD.crs().convert(lon, lat, model.projection, 'F') - elif (model.format == 'netcdf'): + elif (model.format == 'ATLAS-netcdf'): # if reading a netCDF OTIS atlas solution xi, yi, hz = pyTMD.io.ATLAS.read_netcdf_grid( pathlib.Path(model.grid_file).expanduser(), @@ -175,7 +176,7 @@ def check_points(x: np.ndarray, y: np.ndarray, X,Y = np.copy([lon,lat]).astype(np.float64) lt0, = np.nonzero(X < 0) X[lt0] += 360.0 - elif (model.format == 'GOT'): + elif model.format in ('GOT-ascii', 'GOT-netcdf'): # if reading a NASA GOT solution hc, xi, yi, c = pyTMD.io.GOT.read_ascii_file( pathlib.Path(model.model_file[0]).expanduser(), @@ -186,7 +187,7 @@ def check_points(x: np.ndarray, y: np.ndarray, X, Y = np.copy([lon,lat]).astype(np.float64) lt0, = np.nonzero(X < 0) X[lt0] += 360.0 - elif (model.format == 'FES'): + elif (model.format == 'FES-netcdf'): # if reading a FES netCDF solution hc, xi, yi = pyTMD.io.FES.read_netcdf_file( pathlib.Path(model.model_file[0]).expanduser(), diff --git a/pyTMD/compute.py b/pyTMD/compute.py index c8b91f6f..162cf434 100644 --- a/pyTMD/compute.py +++ b/pyTMD/compute.py @@ -6,7 +6,7 @@ Calculates tidal currents at locations and times Ocean and Load Tides -Uses OTIS format tidal solutions provided by Ohio State University and ESR +Uses OTIS format tidal solutions provided by Oregon State University and ESR http://volkov.oce.orst.edu/tides/region.html https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/ ftp://ftp.esr.org/pub/datasets/tmd/ @@ -64,6 +64,10 @@ 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 + renamed format for ATLAS to ATLAS-compact + renamed format for netcdf to ATLAS-netcdf + renamed format for FES to FES-netcdf and added FES-ascii + renamed format for GOT to GOT-ascii and added GOT-netcdf 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 @@ -184,7 +188,7 @@ def tide_elevations( x: np.ndarray, y: np.ndarray, delta_time: np.ndarray, DIRECTORY: str | pathlib.Path | None = None, MODEL: str | None = None, - ATLAS_FORMAT: str = 'netcdf', + ATLAS_FORMAT: str = 'ATLAS-netcdf', GZIP: bool = False, DEFINITION_FILE: str | pathlib.Path | IOBase | None = None, DEFINITION_FORMAT: str = 'ascii', @@ -218,11 +222,8 @@ def tide_elevations( working data directory for tide models MODEL: str or NoneType, default None Tide model to use in correction - ATLAS_FORMAT: str, default 'netcdf' + ATLAS_FORMAT: str, default 'ATLAS-netcdf' ATLAS tide model format - - - ``'OTIS'`` - - ``'netcdf'`` GZIP: bool, default False Tide model files are gzip compressed DEFINITION_FILE: str, pathlib.Path, io.IOBase or NoneType, default None @@ -335,27 +336,29 @@ def tide_elevations( nt = len(ts) # read tidal constants and interpolate to grid points - if model.format in ('OTIS', 'ATLAS', 'TMD3'): + corrections, _, grid = model.format.partition('-') + if model.format in ('OTIS', 'ATLAS-compact', 'TMD3'): amp,ph,D,c = pyTMD.io.OTIS.extract_constants(lon, lat, model.grid_file, - model.model_file, model.projection, type=model.type, + model.model_file, model.projection, type=model.type, grid=corrections, crop=CROP, bounds=BOUNDS, method=METHOD, extrapolate=EXTRAPOLATE, - cutoff=CUTOFF, grid=model.format, apply_flexure=APPLY_FLEXURE) + cutoff=CUTOFF, 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'): + elif model.format in ('ATLAS-netcdf',): amp,ph,D,c = pyTMD.io.ATLAS.extract_constants(lon, lat, model.grid_file, 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'): + elif model.format in ('GOT-ascii', 'GOT-netcdf'): amp,ph,c = pyTMD.io.GOT.extract_constants(lon, lat, model.model_file, - crop=CROP, bounds=BOUNDS, method=METHOD, extrapolate=EXTRAPOLATE, - cutoff=CUTOFF, scale=model.scale, compressed=model.compressed) + grid=grid, 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'): + elif model.format in ('FES-ascii', 'FES-netcdf'): amp,ph = pyTMD.io.FES.extract_constants(lon, lat, model.model_file, type=model.type, version=model.version, crop=CROP, bounds=BOUNDS, method=METHOD, extrapolate=EXTRAPOLATE, cutoff=CUTOFF, @@ -377,11 +380,11 @@ def tide_elevations( tide.mask = np.zeros((ny,nx,nt),dtype=bool) for i in range(nt): TIDE = pyTMD.predict.map(ts.tide[i], hc, c, - deltat=deltat[i], corrections=model.format) + deltat=deltat[i], corrections=corrections) # calculate values for minor constituents by inferrence if INFER_MINOR: MINOR = pyTMD.predict.infer_minor(ts.tide[i], hc, c, - deltat=deltat[i], corrections=model.format) + deltat=deltat[i], corrections=corrections) else: MINOR = np.ma.zeros_like(TIDE) # add major and minor components and reform grid @@ -391,11 +394,11 @@ def tide_elevations( tide = np.ma.zeros((nt), fill_value=FILL_VALUE) tide.mask = np.any(hc.mask,axis=1) tide.data[:] = pyTMD.predict.drift(ts.tide, hc, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) # calculate values for minor constituents by inferrence if INFER_MINOR: minor = pyTMD.predict.infer_minor(ts.tide, hc, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) tide.data[:] += minor.data[:] elif (TYPE.lower() == 'time series'): nstation = len(x) @@ -404,11 +407,11 @@ def tide_elevations( for s in range(nstation): HC = hc[s,None,:] TIDE = pyTMD.predict.time_series(ts.tide, HC, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) # calculate values for minor constituents by inferrence if INFER_MINOR: MINOR = pyTMD.predict.infer_minor(ts.tide, HC, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) else: MINOR = np.ma.zeros_like(TIDE) # add major and minor components @@ -425,7 +428,7 @@ def tide_currents( x: np.ndarray, y: np.ndarray, delta_time: np.ndarray, DIRECTORY: str | pathlib.Path | None = None, MODEL: str | None = None, - ATLAS_FORMAT: str = 'netcdf', + ATLAS_FORMAT: str = 'ATLAS-netcdf', GZIP: bool = False, DEFINITION_FILE: str | pathlib.Path | IOBase | None = None, DEFINITION_FORMAT: str = 'ascii', @@ -458,11 +461,8 @@ def tide_currents( working data directory for tide models MODEL: str or NoneType, default None Tide model to use in correction - ATLAS_FORMAT: str, default 'netcdf' + ATLAS_FORMAT: str, default 'ATLAS-netcdf' ATLAS tide model format - - - ``'OTIS'`` - - ``'netcdf'`` GZIP: bool, default False Tide model files are gzip compressed DEFINITION_FILE: str, pathlib.Path, io.IOBase or NoneType, default None @@ -575,21 +575,22 @@ def tide_currents( # iterate over u and v currents for t in model.type: # read tidal constants and interpolate to grid points - if model.format in ('OTIS', 'ATLAS', 'TMD3'): + corrections, _, grid = model.format.partition('-') + if model.format in ('OTIS', 'ATLAS-compact', 'TMD3'): amp,ph,D,c = pyTMD.io.OTIS.extract_constants(lon, lat, model.grid_file, - model.model_file['u'], model.projection, type=t, + model.model_file['u'], model.projection, type=t, grid=corrections, crop=CROP, bounds=BOUNDS, method=METHOD, extrapolate=EXTRAPOLATE, - cutoff=CUTOFF, grid=model.format) + cutoff=CUTOFF) # use delta time at 2000.0 to match TMD outputs deltat = np.zeros((nt), dtype=np.float64) - elif (model.format == 'netcdf'): + elif model.format in ('ATLAS-netcdf',): amp,ph,D,c = pyTMD.io.ATLAS.extract_constants(lon, lat, model.grid_file, 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'): + elif model.format in ('FES-ascii', 'FES-netcdf'): amp,ph = pyTMD.io.FES.extract_constants(lon, lat, model.model_file[t], type=t, version=model.version, crop=CROP, bounds=BOUNDS, method=METHOD, extrapolate=EXTRAPOLATE, cutoff=CUTOFF, @@ -611,11 +612,11 @@ def tide_currents( tide[t].mask = np.zeros((ny,nx,nt),dtype=bool) for i in range(nt): TIDE = pyTMD.predict.map(ts.tide[i], hc, c, - deltat=deltat[i], corrections=model.format) + deltat=deltat[i], corrections=corrections) # calculate values for minor constituents by inferrence if INFER_MINOR: MINOR = pyTMD.predict.infer_minor(ts.tide[i], hc, c, - deltat=deltat[i], corrections=model.format) + deltat=deltat[i], corrections=corrections) else: MINOR = np.ma.zeros_like(TIDE) # add major and minor components and reform grid @@ -625,11 +626,11 @@ def tide_currents( tide[t] = np.ma.zeros((nt), fill_value=FILL_VALUE) tide[t].mask = np.any(hc.mask,axis=1) tide[t].data[:] = pyTMD.predict.drift(ts.tide, hc, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) # calculate values for minor constituents by inferrence if INFER_MINOR: minor = pyTMD.predict.infer_minor(ts.tide, hc, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) tide[t].data[:] += minor.data[:] elif (TYPE.lower() == 'time series'): nstation = len(x) @@ -638,11 +639,11 @@ def tide_currents( for s in range(nstation): HC = hc[s,None,:] TIDE = pyTMD.predict.time_series(ts.tide, HC, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) # calculate values for minor constituents by inferrence if INFER_MINOR: MINOR = pyTMD.predict.infer_minor(ts.tide, HC, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) else: MINOR = np.ma.zeros_like(TIDE) # add major and minor components diff --git a/pyTMD/compute_tide_corrections.py b/pyTMD/compute_tide_corrections.py index f65ca93a..3a0fe332 100644 --- a/pyTMD/compute_tide_corrections.py +++ b/pyTMD/compute_tide_corrections.py @@ -5,7 +5,7 @@ Calculates tidal elevations for correcting elevation or imagery data Ocean and Load Tides -Uses OTIS format tidal solutions provided by Ohio State University and ESR +Uses OTIS format tidal solutions provided by Oregon State University and ESR http://volkov.oce.orst.edu/tides/region.html https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/ ftp://ftp.esr.org/pub/datasets/tmd/ diff --git a/pyTMD/io/ATLAS.py b/pyTMD/io/ATLAS.py index 259818bd..3b9fff53 100644 --- a/pyTMD/io/ATLAS.py +++ b/pyTMD/io/ATLAS.py @@ -8,7 +8,7 @@ given locations netCDF4 files can be been compressed using gzip -Reads netCDF4 ATLAS tidal solutions provided by Ohio State University and ESR +Reads netCDF4 ATLAS tidal solutions provided by Oregon State University and ESR http://volkov.oce.orst.edu/tides/region.html https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/ ftp://ftp.esr.org/pub/datasets/tmd/ diff --git a/pyTMD/io/GOT.py b/pyTMD/io/GOT.py index ee668287..cbc553be 100644 --- a/pyTMD/io/GOT.py +++ b/pyTMD/io/GOT.py @@ -43,6 +43,7 @@ UPDATE HISTORY: Updated 07/2024: added crop and bounds keywords for trimming model data + use parse function from constituents class to extract names Updated 04/2023: fix repeated longitudinal convention adjustment using pathlib to define and expand tide model paths Updated 03/2023: add basic variable typing to function inputs @@ -547,9 +548,7 @@ def read_ascii_file( with open(input_file, mode="r", encoding='utf8') as f: file_contents = f.read().splitlines() # parse header text - constituent_list = ['Q1','O1','P1','K1','N2','M2','S2','K2','S1','M4'] - regex = re.compile(r'|'.join(constituent_list), re.IGNORECASE) - cons = regex.findall(file_contents[0]).pop().lower() + cons = pyTMD.io.constituents.parse(file_contents[0]) nlat,nlon = np.array(file_contents[2].split(), dtype=int) # longitude range ilat = np.array(file_contents[3].split(), dtype=np.float64) @@ -639,7 +638,7 @@ def read_netcdf_file( amp = fileID.variables['amplitude'][:] ph = fileID.variables['phase'][:] # extract constituent from attribute - cons = fileID.Constituent.lower() + cons = pyTMD.io.constituents.parse(fileID.Constituent) # close the file fileID.close() f.close() if kwargs['compressed'] else None diff --git a/pyTMD/io/OTIS.py b/pyTMD/io/OTIS.py index ff17924d..1fedf114 100644 --- a/pyTMD/io/OTIS.py +++ b/pyTMD/io/OTIS.py @@ -7,7 +7,7 @@ Includes functions to extract tidal harmonic constants from OTIS tide models for given locations -Reads OTIS format tidal solutions provided by Ohio State University and ESR +Reads OTIS format tidal solutions provided by Oregon State University and ESR http://volkov.oce.orst.edu/tides/region.html https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/ ftp://ftp.esr.org/pub/datasets/tmd/ diff --git a/pyTMD/io/constituents.py b/pyTMD/io/constituents.py index ffb41c74..fe230a38 100644 --- a/pyTMD/io/constituents.py +++ b/pyTMD/io/constituents.py @@ -1,7 +1,7 @@ #!/usr/bin/env python u""" constituents.py -Written by Tyler Sutterley (05/2024) +Written by Tyler Sutterley (07/2024) Basic tide model constituent class PYTHON DEPENDENCIES: @@ -10,6 +10,7 @@ https://numpy.org/doc/stable/user/numpy-for-matlab-users.html UPDATE HISTORY: + Updated 07/2024: add function to parse tidal constituents from strings Updated 05/2024: make subscriptable and allow item assignment Updated 01/2024: added properties for Doodson and Cartwright numbers Updated 08/2023: added default for printing constituent class @@ -19,6 +20,7 @@ """ from __future__ import division, annotations +import re import copy import numpy as np import pyTMD.arguments @@ -189,6 +191,43 @@ def cartwright_number(self): # return the list of Cartwright numbers return cartwright_numbers + @staticmethod + def parse(constituent: str) -> str: + """ + Parses for tidal constituents using regular expressions and + remapping of known cases + + Parameters + ---------- + constituent: str + Unparsed tidal constituent name + """ + # list of tidal constituents (not all are included in tidal program) + # include negative look-behind and look-ahead for complex cases + cindex = [r'(? str: def suffix(self) -> str: """Returns format suffix for netCDF4 ATLAS files """ - return '.nc' if (self.format == 'netcdf') else '' + if self.format in ('ATLAS-netcdf','GOT-netcdf'): + return '.nc' + elif self.format in ('GOT-ascii',): + return '.d' + else: + return '' @property def atl03(self) -> str: @@ -1162,6 +1194,14 @@ def description(self) -> str: else: return None + @staticmethod + def formats() -> list: + """ + Returns list of known model formats + """ + return ['OTIS','ATLAS-compact','TMD3','ATLAS-netcdf', + 'GOT-ascii','GOT-netcdf','FES-ascii','FES-netcdf'] + @staticmethod def global_ocean() -> list: """ @@ -1169,15 +1209,15 @@ def global_ocean() -> list: """ return ['TPXO9-atlas','TPXO9-atlas-v2','TPXO9-atlas-v3', 'TPXO9-atlas-v4','TPXO9-atlas-v5','TPXO9.1','TPXO8-atlas', - 'TPXO7.2','GOT4.7','GOT4.8','GOT4.10','FES2014','FES2022', - 'EOT20','HAMTIDE11'] + 'TPXO7.2','GOT4.7','GOT4.8','GOT4.10','GOT5.5', + 'FES2014','FES2022','EOT20','HAMTIDE11'] @staticmethod def global_load() -> list: """ Returns list of global load tide elevation models """ - return ['TPXO7.2_load','GOT4.7_load','GOT4.8_load', + return ['TPXO7.2_load','GOT4.7_load','GOT4.8_load','GOT5.5_load', 'GOT4.10_load','FES2014_load','FES2022_load','EOT20_load'] @staticmethod @@ -1242,8 +1282,8 @@ def ocean_elevation() -> list: 'TPXO9-atlas-v2','TPXO9-atlas-v3','TPXO9-atlas-v4', 'TPXO9-atlas-v5','TPXO9.1','TPXO8-atlas','TPXO7.2', 'AODTM-5','AOTIM-5','AOTIM-5-2018','Arc2kmTM','Gr1kmTM', - 'Gr1km-v2','GOT4.7','GOT4.8','GOT4.10','FES2014','FES2022', - 'EOT20','HAMTIDE11'] + 'Gr1km-v2','GOT4.7','GOT4.8','GOT4.10','GOT5.5', + 'FES2014','FES2022','EOT20','HAMTIDE11'] @staticmethod def load_elevation() -> list: @@ -1251,8 +1291,8 @@ def load_elevation() -> list: Returns list of load tide elevation models """ return ['CATS2008_load','TPXO7.2_load','GOT4.7_load', - 'GOT4.8_load','GOT4.10_load','FES2014_load','FES2022_load', - 'EOT20_load'] + 'GOT4.8_load','GOT4.10_load','GOT5.5_load', + 'FES2014_load','FES2022_load','EOT20_load'] @staticmethod def ocean_current() -> list: @@ -1302,7 +1342,7 @@ def GOT() -> list: Returns list of GOT format models """ return ['GOT4.7','GOT4.7_load','GOT4.8','GOT4.8_load', - 'GOT4.10','GOT4.10_load'] + 'GOT4.10','GOT4.10_load','GOT5.5','GOT5.5_load'] @staticmethod def FES() -> list: @@ -1326,8 +1366,7 @@ def pathfinder(self, model_file: str | pathlib.Path | list): self.directory = pathlib.Path().absolute() # complete model file paths if isinstance(model_file, list): - output_file = [self.model_directory.joinpath( - ''.join([f, self.suffix, self.gzip])) for f in model_file] + output_file = [self.pathfinder(f) for f in model_file] valid = all([f.exists() for f in output_file]) elif isinstance(model_file, str): output_file = self.model_directory.joinpath( @@ -1393,7 +1432,7 @@ def from_ascii(self, fid: io.IOBase): temp = self.from_dict(parameters) # verify model name, format and type assert temp.name - assert temp.format in ('OTIS','ATLAS','TMD3','netcdf','GOT','FES') + temp.validate_format() assert temp.type assert temp.model_file # split type into list if currents (u,v) @@ -1407,7 +1446,7 @@ def from_ascii(self, fid: io.IOBase): # model files can be comma, tab or space delimited # extract full path to tide model files # extract full path to tide grid file - if temp.format in ('OTIS','ATLAS','TMD3'): + if temp.format in ('OTIS','ATLAS-compact','TMD3'): assert temp.grid_file # check if grid file is relative if (temp.directory is not None): @@ -1453,7 +1492,7 @@ def from_ascii(self, fid: io.IOBase): # fully defined single file case temp.model_file = pathlib.Path(temp.model_file).expanduser() temp.model_directory = temp.model_file.parent - elif temp.format in ('netcdf',): + elif temp.format in ('ATLAS-netcdf',): assert temp.grid_file # check if grid file is relative if (temp.directory is not None): @@ -1500,7 +1539,7 @@ def from_ascii(self, fid: io.IOBase): temp.model_file = [pathlib.Path(f).expanduser() for f in re.split(r'[\s\,]+', temp.model_file)] temp.model_directory = temp.model_file[0].parent - elif temp.format in ('FES','GOT'): + elif temp.format in ('FES-ascii','FES-netcdf','GOT-ascii','GOT-netcdf'): # extract model files if (temp.type == ['u','v']) and (temp.directory is not None): # split model file string at semicolon @@ -1548,15 +1587,15 @@ def from_ascii(self, fid: io.IOBase): re.split(r'[\s\,]+', temp.model_file)] temp.model_directory = temp.model_file[0].parent # verify that projection attribute exists for projected models - if temp.format in ('OTIS','ATLAS','TMD3'): + if temp.format in ('OTIS','ATLAS-compact','TMD3'): assert temp.projection # convert scale from string to float - if temp.format in ('netcdf','GOT','FES'): + if temp.format in ('ATLAS-netcdf','GOT-ascii','GOT-netcdf','FES-ascii','FES-netcdf'): assert temp.scale temp.scale = float(temp.scale) # assert that FES model has a version # get model constituents from constituent files - if temp.format in ('FES',): + if temp.format in ('FES-ascii','FES-netcdf',): assert temp.version if (temp.constituents is None): temp.parse_constituents() @@ -1581,14 +1620,14 @@ def from_json(self, fid: io.IOBase): temp = self.from_dict(parameters) # verify model name, format and type assert temp.name - assert temp.format in ('OTIS','ATLAS','TMD3','netcdf','GOT','FES') + temp.validate_format() assert temp.type assert temp.model_file # split model file into list if an ATLAS, GOT or FES file # model files can be comma, tab or space delimited # extract full path to tide model files # extract full path to tide grid file - if temp.format in ('OTIS','ATLAS','TMD3'): + if temp.format in ('OTIS','ATLAS-compact','TMD3'): assert temp.grid_file # check if grid file is relative if (temp.directory is not None): @@ -1633,7 +1672,7 @@ def from_json(self, fid: io.IOBase): # fully defined single file case temp.model_file = pathlib.Path(temp.model_file).expanduser() temp.model_directory = temp.model_file.parent - elif temp.format in ('netcdf',): + elif temp.format in ('ATLAS-netcdf',): assert temp.grid_file # check if grid file is relative if (temp.directory is not None): @@ -1673,7 +1712,7 @@ def from_json(self, fid: io.IOBase): temp.model_file = [pathlib.Path(f).expanduser() for f in temp.model_file] temp.model_directory = temp.model_file[0].parent - elif temp.format in ('FES','GOT'): + elif temp.format in ('FES-ascii','FES-netcdf','GOT-ascii','GOT-netcdf'): # extract model files if (temp.type == ['u','v']) and (temp.directory is not None): # use glob strings to find files in directory @@ -1713,20 +1752,47 @@ def from_json(self, fid: io.IOBase): temp.model_file] temp.model_directory = temp.model_file[0].parent # verify that projection attribute exists for projected models - if temp.format in ('OTIS','ATLAS','TMD3'): + if temp.format in ('OTIS','ATLAS-compact','TMD3'): assert temp.projection # convert scale from string to float - if temp.format in ('netcdf','GOT','FES'): + if temp.format in ('ATLAS-netcdf','GOT-ascii','GOT-netcdf','FES-ascii','FES-netcdf'): assert temp.scale # assert that FES model has a version # get model constituents from constituent files - if temp.format in ('FES',): + if temp.format in ('FES-ascii','FES-netcdf',): assert temp.version if (temp.constituents is None): temp.parse_constituents() # return the model parameters return temp + def validate_format(self): + """Asserts that the model format is a known type""" + # known remapped cases + mapping = [('ATLAS','ATLAS-compact'), ('netcdf','ATLAS-netcdf'), + ('FES','FES-netcdf'), ('GOT','GOT-ascii')] + # iterate over known remapped cases + for m in mapping: + # check if tide model is a remapped case + if (self.format == m[0]): + self.format = m[1] + # assert that tide model is a known format + assert self.format in self.formats() + + def from_dict(self, d: dict): + """ + Create a model object from a python dictionary + + Parameters + ---------- + d: dict + Python dictionary for creating model object + """ + for key, val in d.items(): + setattr(self, key, copy.copy(val)) + # return the model parameters + return self + def parse_constituents(self) -> list: """ Parses tide model files for a list of model constituents @@ -1768,51 +1834,21 @@ def parse_file( constituent: str or list constituent name """ - # list of tidal constituents (not all are included in tidal program) - # include negative look-behind and look-ahead for complex cases - cindex = [r'(? bool: + + @staticmethod + def to_bool(val: str) -> bool: """ Converts strings of True/False to a boolean values diff --git a/pyTMD/tools.py b/pyTMD/tools.py index e22ab07f..5b7d0caf 100644 --- a/pyTMD/tools.py +++ b/pyTMD/tools.py @@ -1,7 +1,7 @@ #!/usr/bin/env python u""" tools.py -Written by Tyler Sutterley (04/2024) +Written by Tyler Sutterley (07/2024) Jupyter notebook, user interface and plotting tools PYTHON DEPENDENCIES: @@ -17,6 +17,7 @@ https://github.com/matplotlib/matplotlib UPDATE HISTORY: + Updated 07/2024: renamed format for netcdf to ATLAS-netcdf Updated 04/2024: use wrapper to importlib for optional dependencies Updated 12/2023: pass through VBox and HBox Updated 08/2023: place matplotlib within try/except statements @@ -83,10 +84,10 @@ def __init__(self, **kwargs): ) # dropdown menu for setting ATLAS format model - atlas_list = ['OTIS','netcdf'] + atlas_list = ['OTIS','ATLAS-netcdf'] self.atlas = ipywidgets.Dropdown( options=atlas_list, - value='netcdf', + value='ATLAS-netcdf', description='ATLAS:', disabled=False, style=self.style, diff --git a/scripts/aviso_fes_tides.py b/scripts/aviso_fes_tides.py index ea4e5a9b..16c9bfd6 100644 --- a/scripts/aviso_fes_tides.py +++ b/scripts/aviso_fes_tides.py @@ -24,8 +24,9 @@ FES2012 FES2014 FES2022 - --load: download load tide model outputs (fes2014) - --currents: download tide model current outputs (fes2012 and fes2014) + --load: download load tide model outputs (FES2014) + --currents: download tide model current outputs (FES2012 and FES2014) + --extrapolated: Download extrapolated tide model outputs (FES2022) -G, --gzip: compress output ascii and netCDF4 tide files -t X, --timeout X: timeout in seconds for blocking operations --log: output log of files downloaded @@ -295,7 +296,7 @@ def ftp_download(logger, ftp, remote_path, local_dir, fileobj = io.BytesIO() ftp.retrbinary(f'RETR {remote_file}', fileobj.write, blocksize=CHUNK) fileobj.seek(0) - # open the AOD1B monthly tar file + # open the tar file tar = tarfile.open(name=remote_path[-1], fileobj=fileobj, mode=TARMODE) # read tar file and extract all files member_files = [m for m in tar.getmembers() if tarfile.TarInfo.isfile(m)] diff --git a/scripts/compute_tidal_currents.py b/scripts/compute_tidal_currents.py index 1069b629..1f056b8f 100755 --- a/scripts/compute_tidal_currents.py +++ b/scripts/compute_tidal_currents.py @@ -4,7 +4,7 @@ Written by Tyler Sutterley (07/2024) Calculates zonal and meridional tidal currents for an input file -Uses OTIS format tidal solutions provided by Ohio State University and ESR +Uses OTIS format tidal solutions provided by Oregon State University and ESR http://volkov.oce.orst.edu/tides/region.html https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/ ftp://ftp.esr.org/pub/datasets/tmd/ @@ -20,7 +20,7 @@ COMMAND LINE OPTIONS: -D X, --directory X: Working data directory -T X, --tide X: Tide model to use in calculating currents - --atlas-format X: ATLAS tide model format (OTIS, netcdf) + --atlas-format X: ATLAS tide model format (OTIS, ATLAS-netcdf) --gzip, -G: Tide model files are gzip compressed --definition-file X: Model definition file for use in calculating currents -C, --crop: Crop tide model to (buffered) bounds of data @@ -100,6 +100,10 @@ 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 + renamed format for ATLAS to ATLAS-compact + renamed format for netcdf to ATLAS-netcdf + renamed format for FES to FES-netcdf and added FES-ascii + renamed format for GOT to GOT-ascii and added GOT-netcdf 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 @@ -198,7 +202,7 @@ def get_projection(attributes, PROJECTION): # compute tides at points and times using tidal model driver algorithms def compute_tidal_currents(tide_dir, input_file, output_file, TIDE_MODEL=None, - ATLAS_FORMAT='netcdf', + ATLAS_FORMAT='ATLAS-netcdf', GZIP=True, DEFINITION_FILE=None, DEFINITION_FORMAT='ascii', @@ -292,19 +296,20 @@ def compute_tidal_currents(tide_dir, input_file, output_file, # iterate over u and v currents for t in model.type: # read tidal constants and interpolate to grid points - if model.format in ('OTIS','ATLAS','TMD3'): + corrections, _, grid = model.format.partition('-') + if model.format in ('OTIS','ATLAS-compact','TMD3'): amp,ph,D,c = pyTMD.io.OTIS.extract_constants(np.ravel(lon), np.ravel(lat), model.grid_file, model.model_file['u'], model.projection, - type=t, crop=CROP, method=METHOD, extrapolate=EXTRAPOLATE, - cutoff=CUTOFF, grid=model.format) + type=t, grid=corrections, crop=CROP, method=METHOD, + extrapolate=EXTRAPOLATE, cutoff=CUTOFF) deltat = np.zeros((nt)) - elif (model.format == 'netcdf'): + elif (model.format == 'ATLAS-netcdf'): amp,ph,D,c = pyTMD.io.ATLAS.extract_constants(np.ravel(lon), np.ravel(lat), model.grid_file, model.model_file[t], type=t, crop=CROP, method=METHOD, extrapolate=EXTRAPOLATE, cutoff=CUTOFF, scale=model.scale, compressed=model.compressed) deltat = np.zeros((nt)) - elif (model.format == 'FES'): + elif (model.format == 'FES-netcdf'): amp,ph = pyTMD.io.FES.extract_constants(np.ravel(lon), np.ravel(lat), model.model_file[t], type=t, version=model.version, crop=CROP, method=METHOD, extrapolate=EXTRAPOLATE, cutoff=CUTOFF, @@ -325,11 +330,11 @@ def compute_tidal_currents(tide_dir, input_file, output_file, tide[t].mask = np.zeros((ny,nx,nt),dtype=bool) for i in range(nt): TIDE = pyTMD.predict.map(ts.tide[i], hc, c, - deltat=deltat[i], corrections=model.format) + deltat=deltat[i], corrections=corrections) # calculate values for minor constituents by inferrence if INFER_MINOR: MINOR = pyTMD.predict.infer_minor(ts.tide[i], hc, c, - deltat=deltat[i], corrections=model.format) + deltat=deltat[i], corrections=corrections) else: MINOR = np.ma.zeros_like(TIDE) # add major and minor components and reform grid @@ -340,11 +345,11 @@ def compute_tidal_currents(tide_dir, input_file, output_file, tide[t] = np.ma.zeros((nt), fill_value=FILL_VALUE) tide[t].mask = np.any(hc.mask,axis=1) tide[t].data[:] = pyTMD.predict.drift(ts.tide, hc, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) # calculate values for minor constituents by inferrence if INFER_MINOR: minor = pyTMD.predict.infer_minor(ts.tide, hc, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) tide[t].data[:] += minor.data[:] elif (TYPE == 'time series'): tide[t] = np.ma.zeros((nstation,nt), fill_value=FILL_VALUE) @@ -353,11 +358,11 @@ def compute_tidal_currents(tide_dir, input_file, output_file, # calculate constituent oscillation for station HC = hc[s,None,:] TIDE = pyTMD.predict.time_series(ts.tide, HC, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) # calculate values for minor constituents by inferrence if INFER_MINOR: MINOR = pyTMD.predict.infer_minor(ts.tide, HC, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) else: MINOR = np.ma.zeros_like(TIDE) # add major and minor components @@ -465,7 +470,8 @@ def arguments(): type=str, choices=choices, help='Tide model to use in calculating currents') parser.add_argument('--atlas-format', - type=str, choices=('OTIS','netcdf'), default='netcdf', + type=str, choices=('OTIS','ATLAS-netcdf'), + default='ATLAS-netcdf', help='ATLAS tide model format') parser.add_argument('--gzip','-G', default=False, action='store_true', diff --git a/scripts/compute_tidal_elevations.py b/scripts/compute_tidal_elevations.py index abe55875..419e9607 100755 --- a/scripts/compute_tidal_elevations.py +++ b/scripts/compute_tidal_elevations.py @@ -4,7 +4,7 @@ Written by Tyler Sutterley (07/2024) Calculates tidal elevations for an input file -Uses OTIS format tidal solutions provided by Ohio State University and ESR +Uses OTIS format tidal solutions provided by Oregon State University and ESR http://volkov.oce.orst.edu/tides/region.html https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/ ftp://ftp.esr.org/pub/datasets/tmd/ @@ -21,7 +21,7 @@ COMMAND LINE OPTIONS: -D X, --directory X: Working data directory -T X, --tide X: Tide model to use in correction - --atlas-format X: ATLAS tide model format (OTIS, netcdf) + --atlas-format X: ATLAS tide model format (OTIS, ATLAS-netcdf) --gzip, -G: Tide model files are gzip compressed --definition-file X: Model definition file for use as correction -C, --crop: Crop tide model to (buffered) bounds of data @@ -103,6 +103,10 @@ 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 + renamed format for ATLAS to ATLAS-compact + renamed format for netcdf to ATLAS-netcdf + renamed format for FES to FES-netcdf and added FES-ascii + renamed format for GOT to GOT-ascii and added GOT-netcdf 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 @@ -202,7 +206,7 @@ def get_projection(attributes, PROJECTION): # compute tides at points and times using tidal model driver algorithms def compute_tidal_elevations(tide_dir, input_file, output_file, TIDE_MODEL=None, - ATLAS_FORMAT='netcdf', + ATLAS_FORMAT='ATLAS-netcdf', GZIP=True, DEFINITION_FILE=None, DEFINITION_FORMAT='ascii', @@ -292,25 +296,27 @@ def compute_tidal_elevations(tide_dir, input_file, output_file, nt = len(ts) # read tidal constants and interpolate to grid points - if model.format in ('OTIS','ATLAS','TMD3'): + corrections, _, grid = model.format.partition('-') + if model.format in ('OTIS','ATLAS-compact','TMD3'): amp,ph,D,c = pyTMD.io.OTIS.extract_constants(np.ravel(lon), np.ravel(lat), model.grid_file, model.model_file, model.projection, - type=model.type, crop=CROP, method=METHOD, extrapolate=EXTRAPOLATE, - cutoff=CUTOFF, grid=model.format, apply_flexure=APPLY_FLEXURE) + type=model.type, grid=corrections, crop=CROP, method=METHOD, + extrapolate=EXTRAPOLATE, cutoff=CUTOFF, apply_flexure=APPLY_FLEXURE) deltat = np.zeros((nt)) - elif (model.format == 'netcdf'): + elif (model.format == 'ATLAS-netcdf'): amp,ph,D,c = pyTMD.io.ATLAS.extract_constants(np.ravel(lon), np.ravel(lat), model.grid_file, model.model_file, type=model.type, crop=CROP, method=METHOD, extrapolate=EXTRAPOLATE, cutoff=CUTOFF, scale=model.scale, compressed=model.compressed) deltat = np.zeros((nt)) - elif (model.format == 'GOT'): + elif model.format in ('GOT-ascii', 'GOT-netcdf'): amp,ph,c = pyTMD.io.GOT.extract_constants(np.ravel(lon), np.ravel(lat), - model.model_file, crop=CROP, method=METHOD, extrapolate=EXTRAPOLATE, - cutoff=CUTOFF, scale=model.scale, compressed=model.compressed) + model.model_file, grid=grid, crop=CROP, method=METHOD, + extrapolate=EXTRAPOLATE, cutoff=CUTOFF, scale=model.scale, + compressed=model.compressed) # delta time (TT - UT1) deltat = ts.tt_ut1 - elif (model.format == 'FES'): + elif (model.format == 'FES-netcdf'): amp,ph = pyTMD.io.FES.extract_constants(np.ravel(lon), np.ravel(lat), model.model_file, type=model.type, version=model.version, crop=CROP, method=METHOD, extrapolate=EXTRAPOLATE, cutoff=CUTOFF, @@ -332,11 +338,11 @@ def compute_tidal_elevations(tide_dir, input_file, output_file, tide.mask = np.zeros((ny,nx,nt),dtype=bool) for i in range(nt): TIDE = pyTMD.predict.map(ts.tide[i], hc, c, - deltat=deltat[i], corrections=model.format) + deltat=deltat[i], corrections=corrections) # calculate values for minor constituents by inferrence if INFER_MINOR: MINOR = pyTMD.predict.infer_minor(ts.tide[i], hc, c, - deltat=deltat[i], corrections=model.format) + deltat=deltat[i], corrections=corrections) else: MINOR = np.ma.zeros_like(TIDE) # add major and minor components and reform grid @@ -346,11 +352,11 @@ def compute_tidal_elevations(tide_dir, input_file, output_file, tide = np.ma.zeros((nt), fill_value=FILL_VALUE) tide.mask = np.any(hc.mask,axis=1) tide.data[:] = pyTMD.predict.drift(ts.tide, hc, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) # calculate values for minor constituents by inferrence if INFER_MINOR: minor = pyTMD.predict.infer_minor(ts.tide, hc, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) tide.data[:] += minor.data[:] elif (TYPE == 'time series'): tide = np.ma.zeros((nstation,nt), fill_value=FILL_VALUE) @@ -359,11 +365,11 @@ def compute_tidal_elevations(tide_dir, input_file, output_file, # calculate constituent oscillation for station HC = hc[s,None,:] TIDE = pyTMD.predict.time_series(ts.tide, HC, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) # calculate values for minor constituents by inferrence if INFER_MINOR: MINOR = pyTMD.predict.infer_minor(ts.tide, HC, c, - deltat=deltat, corrections=model.format) + deltat=deltat, corrections=corrections) else: MINOR = np.ma.zeros_like(TIDE) # add major and minor components @@ -461,7 +467,8 @@ def arguments(): type=str, choices=choices, help='Tide model to use in correction') parser.add_argument('--atlas-format', - type=str, choices=('OTIS','netcdf'), default='netcdf', + type=str, choices=('OTIS','ATLAS-netcdf'), + default='ATLAS-netcdf', help='ATLAS tide model format') parser.add_argument('--gzip','-G', default=False, action='store_true', diff --git a/scripts/gsfc_got_tides.py b/scripts/gsfc_got_tides.py new file mode 100644 index 00000000..804e2204 --- /dev/null +++ b/scripts/gsfc_got_tides.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python +u""" +gsfc_got_tides.py +Written by Tyler Sutterley (07/2024) +Download GSFC Global Ocean Tide (GOT) models + +CALLING SEQUENCE: + python gsfc_got_tides.py --tide=GOT5.6 + +COMMAND LINE OPTIONS: + --help: list the command line options + -D X, --directory X: working data directory + -T X, --tide X: GOT tide model to download + GOT4.8 + GOT4.10 + GOT5.5 + GOT5.5D + GOT5.6 + --format: GOT tide model format to download + ascii + netCDF + -G, --gzip: compress output ascii and netCDF4 tide files + -t X, --timeout X: timeout in seconds for blocking operations + -M X, --mode X: Local permissions mode of the files downloaded + +PYTHON DEPENDENCIES: + future: Compatibility layer between Python 2 and Python 3 + https://python-future.org/ + +PROGRAM DEPENDENCIES: + utilities.py: download and management utilities for syncing files + +UPDATE HISTORY: + Written 07/2024 +""" +from __future__ import print_function, annotations + +import re +import gzip +import shutil +import logging +import pathlib +import tarfile +import argparse +import posixpath +import pyTMD.utilities + +# PURPOSE: Download Arctic Ocean Tide Models from the NSF ArcticData archive +def gsfc_got_tides(MODEL: str, + DIRECTORY: str | pathlib.Path | None = None, + FORMAT: str = 'netcdf', + GZIP: bool = False, + TIMEOUT: int | None = None, + MODE: oct = 0o775): + + # create logger for verbosity level + logger = pyTMD.utilities.build_logger(__name__,level=logging.INFO) + # if compressing the output files + opener = gzip.open if GZIP else open + + # url for each tide model tarfile + PATH = {} + PATH['GOT4.8'] = ['2022-07','got4.8.tar.gz'] + PATH['GOT4.10'] = ['2023-12','got4.10c.tar.gz'] + PATH['GOT5.5'] = ['2024-07','GOT5.5.tar%201.gz'] + PATH['GOT5.5D'] = ['2024-07','GOT5.5D.tar%201.gz'] + PATH['GOT5.6'] = ['2024-07','GOT5.6.tar%201.gz'] + + # recursively create directories if non-existent + DIRECTORY = pathlib.Path(DIRECTORY).expanduser().absolute() + DIRECTORY.mkdir(MODE, parents=True, exist_ok=True) + + # build host url for model + URL = ['https://earth.gsfc.nasa.gov','sites','default','files',*PATH[MODEL]] + # download tarfile from host + logger.info(f'{posixpath.join(*URL)} -->\n') + fileobj = pyTMD.utilities.from_http(URL, timeout=TIMEOUT) + # open the tar file + tar = tarfile.open(name=PATH[MODEL][-1], fileobj=fileobj, mode='r:gz') + # read tar file and extract all files + member_files = [m for m in tar.getmembers() if tarfile.TarInfo.isfile(m)] + for m in member_files: + # extract file contents to new file + base, sfx = posixpath.splitext(m.name) + # skip files that are not in the desired format + if (sfx == '.nc') and (FORMAT == 'ascii'): + continue + elif (sfx == '.d') and (FORMAT == 'netcdf'): + continue + elif re.match(r'^._', posixpath.basename(m.name)): + continue + # output file name + member = m.name.replace("'","") + output = f'{member}.gz' if sfx in ('.d','.nc') and GZIP else member + local_file = DIRECTORY.joinpath(*posixpath.split(output)) + # check if the local file exists + if local_file.exists() and newer(m.mtime, local_file.stat().st_mtime): + # check the modification time of the local file + # if remote file is newer: overwrite the local file + continue + # print the file being transferred + logger.info(f'\t{str(local_file)}') + # recursively create output directory if non-existent + local_file.parent.mkdir(mode=MODE, parents=True, exist_ok=True) + # extract file to local directory + with tar.extractfile(m) as fi,opener(local_file, 'wb') as fo: + shutil.copyfileobj(fi, fo) + # get last modified date of remote file within tar file + # keep remote modification time of file and local access time + pathlib.os.utime(local_file, (local_file.stat().st_atime, m.mtime)) + local_file.chmod(mode=MODE) + +# PURPOSE: compare the modification time of two files +def newer(t1: int, t2: int) -> bool: + return (pyTMD.utilities.even(t1) <= pyTMD.utilities.even(t2)) + +# PURPOSE: create argument parser +def arguments(): + parser = argparse.ArgumentParser( + description="""Download Global Ocean Tide models from NASA + Goddard Space Flight Center (GSFC) + """, + fromfile_prefix_chars="@" + ) + parser.convert_arg_line_to_args = pyTMD.utilities.convert_arg_line_to_args + # command line parameters + # working data directory for location of tide models + parser.add_argument('--directory','-D', + type=pathlib.Path, default=pathlib.Path.cwd(), + help='Working data directory') + # Global Ocean Tide model to download + parser.add_argument('--tide','-T', + metavar='TIDE', type=str, nargs='+', default=['GOT5.5'], + choices=('GOT4.8','GOT4.10','GOT5.5','GOT5.5D','GOT5.6'), + help='Global Ocean Tide model to download') + # Global Ocean Tide model format to download + parser.add_argument('--format', + type=str, default='netcdf', + choices=('ascii','netcdf'), + help='Global Ocean Tide model format to download') + # compress output ascii and netCDF4 tide files with gzip + parser.add_argument('--gzip','-G', + default=False, action='store_true', + help='Compress output ascii and netCDF tide files') + # connection timeout + parser.add_argument('--timeout','-t', + type=int, default=360, + help='Timeout in seconds for blocking operations') + # permissions mode of the local directories and files (number in octal) + parser.add_argument('--mode','-M', + type=lambda x: int(x,base=8), default=0o775, + help='Permissions mode of the files downloaded') + # return the parser + return parser + +# This is the main part of the program that calls the individual functions +def main(): + # Read the system arguments listed after the program + parser = arguments() + args,_ = parser.parse_known_args() + + # check internet connection before attempting to run program + if pyTMD.utilities.check_connection('https://earth.gsfc.nasa.gov'): + for m in args.tide: + gsfc_got_tides(m, + DIRECTORY=args.directory, + FORMAT=args.format, + GZIP=args.gzip, + TIMEOUT=args.timeout, + MODE=args.mode) + +# run main program +if __name__ == '__main__': + main() diff --git a/scripts/reduce_OTIS_files.py b/scripts/reduce_OTIS_files.py index 1e1e2caa..da075d7f 100644 --- a/scripts/reduce_OTIS_files.py +++ b/scripts/reduce_OTIS_files.py @@ -1,7 +1,7 @@ #!/usr/bin/env python u""" reduce_OTIS_files.py -Written by Tyler Sutterley (04/2024) +Written by Tyler Sutterley (07/2024) Read OTIS-format tidal files and reduce to a regional subset COMMAND LINE OPTIONS: @@ -28,6 +28,7 @@ crs.py: Coordinate Reference System (CRS) routines UPDATE HISTORY: + Updated 07/2024: renamed format for ATLAS to ATLAS-compact Updated 04/2024: add debug mode printing input arguments use wrapper to importlib for optional dependencies Updated 12/2023: use new crs class for coordinate reprojection @@ -89,7 +90,7 @@ def make_regional_OTIS_files(tide_dir, TIDE_MODEL, new_model_file = {} # read the OTIS-format tide grid file - if (model.format == 'ATLAS'): + if (model.format == 'ATLAS-compact'): # if reading a global solution with localized solutions x0,y0,hz0,mz0,iob,dt,pmask,local = pyTMD.io.OTIS.read_atlas_grid( model.grid_file) @@ -147,7 +148,7 @@ def make_regional_OTIS_files(tide_dir, TIDE_MODEL, z1 = np.zeros((ny,nx,nc),dtype=np.complex64) for i,c in enumerate(constituents): # read constituent from elevation file - if (model.format == 'ATLAS'): + if (model.format == 'ATLAS-compact'): z0,zlocal = pyTMD.io.OTIS.read_atlas_elevation( model_file['z'], i, c) xi,yi,z=pyTMD.io.OTIS.combine_atlas_model(x0, y0, z0, pmask, @@ -177,7 +178,7 @@ def make_regional_OTIS_files(tide_dir, TIDE_MODEL, v1 = np.zeros((ny,nx,nc),dtype=np.complex64) for i,c in enumerate(constituents): # read constituent from transport file - if (model.format == 'ATLAS'): + if (model.format == 'ATLAS-compact'): u0,v0,uvlocal = pyTMD.io.OTIS.read_atlas_transport( model_file['u'], i, c) xi,yi,u = pyTMD.io.OTIS.combine_atlas_model(x0, y0, u0, pmask, diff --git a/setup.py b/setup.py index 63def772..d4a24828 100644 --- a/setup.py +++ b/setup.py @@ -8,8 +8,8 @@ log = logging.getLogger() # package description and keywords -description = ('Tide Model Driver to read OTIS, GOT and FES formatted tidal ' - 'solutions and make tidal predictions') +description = ('Tide Model Driver to read OTIS, ATLAS, GOT and FES ' + 'formatted tidal solutions and make tidal predictions') keywords = 'Ocean Tides, Load Tides, Pole Tides, Tidal Prediction, OTIS, GOT, FES' # get long_description from README.rst with open('README.rst', mode='r', encoding='utf8') as fh: diff --git a/test/model_FES2012.json b/test/model_FES2012.json index 7e827b1b..5216f39b 100644 --- a/test/model_FES2012.json +++ b/test/model_FES2012.json @@ -1 +1 @@ -{"format": "FES", "name": "FES2012", "model_file": "fes2012/*_FES2012_SLEV.nc.gz", "type": "z", "version": "FES2012", "variable": "tide_ocean", "scale": 0.01, "compressed": true, "reference": "https://www.aviso.altimetry.fr/en/data/products/auxiliary-products/global-tide-fes.html"} \ No newline at end of file +{"format": "FES-netcdf", "name": "FES2012", "model_file": "fes2012/*_FES2012_SLEV.nc.gz", "type": "z", "version": "FES2012", "variable": "tide_ocean", "scale": 0.01, "compressed": true, "reference": "https://www.aviso.altimetry.fr/en/data/products/auxiliary-products/global-tide-fes.html"} \ No newline at end of file diff --git a/test/model_FES2014.json b/test/model_FES2014.json index 0e7e0370..dd98a36a 100644 --- a/test/model_FES2014.json +++ b/test/model_FES2014.json @@ -1 +1 @@ -{"format": "FES", "name": "FES2014", "model_file": ["fes2014/ocean_tide/2n2.nc.gz", "fes2014/ocean_tide/eps2.nc.gz", "fes2014/ocean_tide/j1.nc.gz", "fes2014/ocean_tide/k1.nc.gz", "fes2014/ocean_tide/k2.nc.gz", "fes2014/ocean_tide/l2.nc.gz", "fes2014/ocean_tide/la2.nc.gz", "fes2014/ocean_tide/m2.nc.gz", "fes2014/ocean_tide/m3.nc.gz", "fes2014/ocean_tide/m4.nc.gz", "fes2014/ocean_tide/m6.nc.gz", "fes2014/ocean_tide/m8.nc.gz", "fes2014/ocean_tide/mf.nc.gz", "fes2014/ocean_tide/mks2.nc.gz", "fes2014/ocean_tide/mm.nc.gz", "fes2014/ocean_tide/mn4.nc.gz", "fes2014/ocean_tide/ms4.nc.gz", "fes2014/ocean_tide/msf.nc.gz", "fes2014/ocean_tide/msqm.nc.gz", "fes2014/ocean_tide/mtm.nc.gz", "fes2014/ocean_tide/mu2.nc.gz", "fes2014/ocean_tide/n2.nc.gz", "fes2014/ocean_tide/n4.nc.gz", "fes2014/ocean_tide/nu2.nc.gz", "fes2014/ocean_tide/o1.nc.gz", "fes2014/ocean_tide/p1.nc.gz", "fes2014/ocean_tide/q1.nc.gz", "fes2014/ocean_tide/r2.nc.gz", "fes2014/ocean_tide/s1.nc.gz", "fes2014/ocean_tide/s2.nc.gz", "fes2014/ocean_tide/s4.nc.gz", "fes2014/ocean_tide/sa.nc.gz", "fes2014/ocean_tide/ssa.nc.gz", "fes2014/ocean_tide/t2.nc.gz"], "constituents": ["2n2", "eps2", "j1", "k1", "k2", "l2", "lambda2", "m2", "m3", "m4", "m6", "m8", "mf", "mks2", "mm", "mn4", "ms4", "msf", "msqm", "mtm", "mu2", "n2", "n4", "nu2", "o1", "p1", "q1", "r2", "s1", "s2", "s4", "sa", "ssa", "t2"], "type": "z", "version": "FES2014", "variable": "tide_ocean", "scale": 0.01, "compressed": true, "reference": "https://www.aviso.altimetry.fr/en/data/products/auxiliary-products/global-tide-fes.html"} \ No newline at end of file +{"format": "FES-netcdf", "name": "FES2014", "model_file": ["fes2014/ocean_tide/2n2.nc.gz", "fes2014/ocean_tide/eps2.nc.gz", "fes2014/ocean_tide/j1.nc.gz", "fes2014/ocean_tide/k1.nc.gz", "fes2014/ocean_tide/k2.nc.gz", "fes2014/ocean_tide/l2.nc.gz", "fes2014/ocean_tide/la2.nc.gz", "fes2014/ocean_tide/m2.nc.gz", "fes2014/ocean_tide/m3.nc.gz", "fes2014/ocean_tide/m4.nc.gz", "fes2014/ocean_tide/m6.nc.gz", "fes2014/ocean_tide/m8.nc.gz", "fes2014/ocean_tide/mf.nc.gz", "fes2014/ocean_tide/mks2.nc.gz", "fes2014/ocean_tide/mm.nc.gz", "fes2014/ocean_tide/mn4.nc.gz", "fes2014/ocean_tide/ms4.nc.gz", "fes2014/ocean_tide/msf.nc.gz", "fes2014/ocean_tide/msqm.nc.gz", "fes2014/ocean_tide/mtm.nc.gz", "fes2014/ocean_tide/mu2.nc.gz", "fes2014/ocean_tide/n2.nc.gz", "fes2014/ocean_tide/n4.nc.gz", "fes2014/ocean_tide/nu2.nc.gz", "fes2014/ocean_tide/o1.nc.gz", "fes2014/ocean_tide/p1.nc.gz", "fes2014/ocean_tide/q1.nc.gz", "fes2014/ocean_tide/r2.nc.gz", "fes2014/ocean_tide/s1.nc.gz", "fes2014/ocean_tide/s2.nc.gz", "fes2014/ocean_tide/s4.nc.gz", "fes2014/ocean_tide/sa.nc.gz", "fes2014/ocean_tide/ssa.nc.gz", "fes2014/ocean_tide/t2.nc.gz"], "constituents": ["2n2", "eps2", "j1", "k1", "k2", "l2", "lambda2", "m2", "m3", "m4", "m6", "m8", "mf", "mks2", "mm", "mn4", "ms4", "msf", "msqm", "mtm", "mu2", "n2", "n4", "nu2", "o1", "p1", "q1", "r2", "s1", "s2", "s4", "sa", "ssa", "t2"], "type": "z", "version": "FES2014", "variable": "tide_ocean", "scale": 0.01, "compressed": true, "reference": "https://www.aviso.altimetry.fr/en/data/products/auxiliary-products/global-tide-fes.html"} \ No newline at end of file diff --git a/test/model_FES2014_currents.json b/test/model_FES2014_currents.json index 21852d52..8a7292b4 100644 --- a/test/model_FES2014_currents.json +++ b/test/model_FES2014_currents.json @@ -1 +1 @@ -{"format": "FES", "name": "FES2014", "model_file": {"u": ["fes2014/eastward_velocity/2n2.nc.gz", "fes2014/eastward_velocity/eps2.nc.gz", "fes2014/eastward_velocity/j1.nc.gz", "fes2014/eastward_velocity/k1.nc.gz", "fes2014/eastward_velocity/k2.nc.gz", "fes2014/eastward_velocity/l2.nc.gz", "fes2014/eastward_velocity/la2.nc.gz", "fes2014/eastward_velocity/m2.nc.gz", "fes2014/eastward_velocity/m3.nc.gz", "fes2014/eastward_velocity/m4.nc.gz", "fes2014/eastward_velocity/m6.nc.gz", "fes2014/eastward_velocity/m8.nc.gz", "fes2014/eastward_velocity/mf.nc.gz", "fes2014/eastward_velocity/mks2.nc.gz", "fes2014/eastward_velocity/mm.nc.gz", "fes2014/eastward_velocity/mn4.nc.gz", "fes2014/eastward_velocity/ms4.nc.gz", "fes2014/eastward_velocity/msf.nc.gz", "fes2014/eastward_velocity/msqm.nc.gz", "fes2014/eastward_velocity/mtm.nc.gz", "fes2014/eastward_velocity/mu2.nc.gz", "fes2014/eastward_velocity/n2.nc.gz", "fes2014/eastward_velocity/n4.nc.gz", "fes2014/eastward_velocity/nu2.nc.gz", "fes2014/eastward_velocity/o1.nc.gz", "fes2014/eastward_velocity/p1.nc.gz", "fes2014/eastward_velocity/q1.nc.gz", "fes2014/eastward_velocity/r2.nc.gz", "fes2014/eastward_velocity/s1.nc.gz", "fes2014/eastward_velocity/s2.nc.gz", "fes2014/eastward_velocity/s4.nc.gz", "fes2014/eastward_velocity/sa.nc.gz", "fes2014/eastward_velocity/ssa.nc.gz", "fes2014/eastward_velocity/t2.nc.gz"], "v": ["fes2014/northward_velocity/2n2.nc.gz", "fes2014/northward_velocity/eps2.nc.gz", "fes2014/northward_velocity/j1.nc.gz", "fes2014/northward_velocity/k1.nc.gz", "fes2014/northward_velocity/k2.nc.gz", "fes2014/northward_velocity/l2.nc.gz", "fes2014/northward_velocity/la2.nc.gz", "fes2014/northward_velocity/m2.nc.gz", "fes2014/northward_velocity/m3.nc.gz", "fes2014/northward_velocity/m4.nc.gz", "fes2014/northward_velocity/m6.nc.gz", "fes2014/northward_velocity/m8.nc.gz", "fes2014/northward_velocity/mf.nc.gz", "fes2014/northward_velocity/mks2.nc.gz", "fes2014/northward_velocity/mm.nc.gz", "fes2014/northward_velocity/mn4.nc.gz", "fes2014/northward_velocity/ms4.nc.gz", "fes2014/northward_velocity/msf.nc.gz", "fes2014/northward_velocity/msqm.nc.gz", "fes2014/northward_velocity/mtm.nc.gz", "fes2014/northward_velocity/mu2.nc.gz", "fes2014/northward_velocity/n2.nc.gz", "fes2014/northward_velocity/n4.nc.gz", "fes2014/northward_velocity/nu2.nc.gz", "fes2014/northward_velocity/o1.nc.gz", "fes2014/northward_velocity/p1.nc.gz", "fes2014/northward_velocity/q1.nc.gz", "fes2014/northward_velocity/r2.nc.gz", "fes2014/northward_velocity/s1.nc.gz", "fes2014/northward_velocity/s2.nc.gz", "fes2014/northward_velocity/s4.nc.gz", "fes2014/northward_velocity/sa.nc.gz", "fes2014/northward_velocity/ssa.nc.gz", "fes2014/northward_velocity/t2.nc.gz"]}, "constituents": ["2n2", "eps2", "j1", "k1", "k2", "l2", "lambda2", "m2", "m3", "m4", "m6", "m8", "mf", "mks2", "mm", "mn4", "ms4", "msf", "msqm", "mtm", "mu2", "n2", "n4", "nu2", "o1", "p1", "q1", "r2", "s1", "s2", "s4", "sa", "ssa", "t2"], "type": ["u", "v"], "version": "FES2014", "scale": 1.0, "compressed": true, "reference": "https://www.aviso.altimetry.fr/en/data/products/auxiliary-products/global-tide-fes.html"} \ No newline at end of file +{"format": "FES-netcdf", "name": "FES2014", "model_file": {"u": ["fes2014/eastward_velocity/2n2.nc.gz", "fes2014/eastward_velocity/eps2.nc.gz", "fes2014/eastward_velocity/j1.nc.gz", "fes2014/eastward_velocity/k1.nc.gz", "fes2014/eastward_velocity/k2.nc.gz", "fes2014/eastward_velocity/l2.nc.gz", "fes2014/eastward_velocity/la2.nc.gz", "fes2014/eastward_velocity/m2.nc.gz", "fes2014/eastward_velocity/m3.nc.gz", "fes2014/eastward_velocity/m4.nc.gz", "fes2014/eastward_velocity/m6.nc.gz", "fes2014/eastward_velocity/m8.nc.gz", "fes2014/eastward_velocity/mf.nc.gz", "fes2014/eastward_velocity/mks2.nc.gz", "fes2014/eastward_velocity/mm.nc.gz", "fes2014/eastward_velocity/mn4.nc.gz", "fes2014/eastward_velocity/ms4.nc.gz", "fes2014/eastward_velocity/msf.nc.gz", "fes2014/eastward_velocity/msqm.nc.gz", "fes2014/eastward_velocity/mtm.nc.gz", "fes2014/eastward_velocity/mu2.nc.gz", "fes2014/eastward_velocity/n2.nc.gz", "fes2014/eastward_velocity/n4.nc.gz", "fes2014/eastward_velocity/nu2.nc.gz", "fes2014/eastward_velocity/o1.nc.gz", "fes2014/eastward_velocity/p1.nc.gz", "fes2014/eastward_velocity/q1.nc.gz", "fes2014/eastward_velocity/r2.nc.gz", "fes2014/eastward_velocity/s1.nc.gz", "fes2014/eastward_velocity/s2.nc.gz", "fes2014/eastward_velocity/s4.nc.gz", "fes2014/eastward_velocity/sa.nc.gz", "fes2014/eastward_velocity/ssa.nc.gz", "fes2014/eastward_velocity/t2.nc.gz"], "v": ["fes2014/northward_velocity/2n2.nc.gz", "fes2014/northward_velocity/eps2.nc.gz", "fes2014/northward_velocity/j1.nc.gz", "fes2014/northward_velocity/k1.nc.gz", "fes2014/northward_velocity/k2.nc.gz", "fes2014/northward_velocity/l2.nc.gz", "fes2014/northward_velocity/la2.nc.gz", "fes2014/northward_velocity/m2.nc.gz", "fes2014/northward_velocity/m3.nc.gz", "fes2014/northward_velocity/m4.nc.gz", "fes2014/northward_velocity/m6.nc.gz", "fes2014/northward_velocity/m8.nc.gz", "fes2014/northward_velocity/mf.nc.gz", "fes2014/northward_velocity/mks2.nc.gz", "fes2014/northward_velocity/mm.nc.gz", "fes2014/northward_velocity/mn4.nc.gz", "fes2014/northward_velocity/ms4.nc.gz", "fes2014/northward_velocity/msf.nc.gz", "fes2014/northward_velocity/msqm.nc.gz", "fes2014/northward_velocity/mtm.nc.gz", "fes2014/northward_velocity/mu2.nc.gz", "fes2014/northward_velocity/n2.nc.gz", "fes2014/northward_velocity/n4.nc.gz", "fes2014/northward_velocity/nu2.nc.gz", "fes2014/northward_velocity/o1.nc.gz", "fes2014/northward_velocity/p1.nc.gz", "fes2014/northward_velocity/q1.nc.gz", "fes2014/northward_velocity/r2.nc.gz", "fes2014/northward_velocity/s1.nc.gz", "fes2014/northward_velocity/s2.nc.gz", "fes2014/northward_velocity/s4.nc.gz", "fes2014/northward_velocity/sa.nc.gz", "fes2014/northward_velocity/ssa.nc.gz", "fes2014/northward_velocity/t2.nc.gz"]}, "constituents": ["2n2", "eps2", "j1", "k1", "k2", "l2", "lambda2", "m2", "m3", "m4", "m6", "m8", "mf", "mks2", "mm", "mn4", "ms4", "msf", "msqm", "mtm", "mu2", "n2", "n4", "nu2", "o1", "p1", "q1", "r2", "s1", "s2", "s4", "sa", "ssa", "t2"], "type": ["u", "v"], "version": "FES2014", "scale": 1.0, "compressed": true, "reference": "https://www.aviso.altimetry.fr/en/data/products/auxiliary-products/global-tide-fes.html"} \ No newline at end of file diff --git a/test/model_FES2022b_extrapolated.json b/test/model_FES2022b_extrapolated.json index 30049e5a..d9b66910 100644 --- a/test/model_FES2022b_extrapolated.json +++ b/test/model_FES2022b_extrapolated.json @@ -1 +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"} \ No newline at end of file +{"format": "FES-netcdf", "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"} \ No newline at end of file diff --git a/test/model_GOT4.10.json b/test/model_GOT4.10.json index 07ac9f0b..7e57b7fa 100644 --- a/test/model_GOT4.10.json +++ b/test/model_GOT4.10.json @@ -1 +1 @@ -{"format": "GOT", "name": "GOT4.10", "model_file": ["GOT4.10c/grids_loadtide/k1load.d.gz", "GOT4.10c/grids_loadtide/k2load.d.gz", "GOT4.10c/grids_loadtide/m2load.d.gz", "GOT4.10c/grids_loadtide/m4load.d.gz", "GOT4.10c/grids_loadtide/n2load.d.gz", "GOT4.10c/grids_loadtide/o1load.d.gz", "GOT4.10c/grids_loadtide/p1load.d.gz", "GOT4.10c/grids_loadtide/q1load.d.gz", "GOT4.10c/grids_loadtide/s1load.d.gz", "GOT4.10c/grids_loadtide/s2load.d.gz"], "type": "z", "variable": "tide_load", "version": "4.10", "scale": 0.001, "compressed": true, "reference": "https://ntrs.nasa.gov/citations/19990089548"} \ No newline at end of file +{"format": "GOT-ascii", "name": "GOT4.10", "model_file": ["GOT4.10c/grids_loadtide/k1load.d.gz", "GOT4.10c/grids_loadtide/k2load.d.gz", "GOT4.10c/grids_loadtide/m2load.d.gz", "GOT4.10c/grids_loadtide/m4load.d.gz", "GOT4.10c/grids_loadtide/n2load.d.gz", "GOT4.10c/grids_loadtide/o1load.d.gz", "GOT4.10c/grids_loadtide/p1load.d.gz", "GOT4.10c/grids_loadtide/q1load.d.gz", "GOT4.10c/grids_loadtide/s1load.d.gz", "GOT4.10c/grids_loadtide/s2load.d.gz"], "type": "z", "variable": "tide_load", "version": "4.10", "scale": 0.001, "compressed": true, "reference": "https://ntrs.nasa.gov/citations/19990089548"} \ No newline at end of file diff --git a/test/model_GOT5.5D.json b/test/model_GOT5.5D.json new file mode 100644 index 00000000..fcf0441a --- /dev/null +++ b/test/model_GOT5.5D.json @@ -0,0 +1 @@ +{"format": "GOT-netcdf", "name": "GOT5.5D", "model_file": ["GOT5.5/ocean_tides/2n2.nc", "GOT5.5/ocean_tides/j1.nc", "GOT5.5D/ocean_tides/k1_5.5D.nc", "GOT5.5/ocean_tides/k2.nc", "GOT5.5D/ocean_tides/m2_5.5D.nc", "GOT5.5/ocean_tides/m4.nc", "GOT5.5/ocean_tides/ms4.nc", "GOT5.5/ocean_tides/mu2.nc", "GOT5.5/ocean_tides/n2.nc", "GOT5.5/ocean_tides/o1.nc", "GOT5.5/ocean_tides/oo1.nc", "GOT5.5D/ocean_tides/p1_5.5D.nc", "GOT5.5/ocean_tides/q1.nc", "GOT5.5D/ocean_tides/s1_5.5D.nc", "GOT5.5D/ocean_tides/s2_5.5D.nc", "GOT5.5/ocean_tides/sig1.nc"], "type": "z", "variable": "tide_ocean", "version": "5.5", "scale": 0.01, "compressed": false, "reference": "https://ntrs.nasa.gov/citations/19990089548"} \ No newline at end of file diff --git a/test/model_GOT5.6.json b/test/model_GOT5.6.json new file mode 100644 index 00000000..997ca7a4 --- /dev/null +++ b/test/model_GOT5.6.json @@ -0,0 +1 @@ +{"format": "GOT-netcdf", "name": "GOT5.6", "model_file": ["GOT5.5/ocean_tides/2n2.nc", "GOT5.5/ocean_tides/j1.nc", "GOT5.5/ocean_tides/k1.nc", "GOT5.5/ocean_tides/k2.nc", "GOT5.6/ocean_tides/l2.nc", "GOT5.6/ocean_tides/m1.nc", "GOT5.5/ocean_tides/m2.nc", "GOT5.6/ocean_tides/m3.nc", "GOT5.5/ocean_tides/m4.nc", "GOT5.5/ocean_tides/ms4.nc", "GOT5.5/ocean_tides/mu2.nc", "GOT5.6/ocean_tides/n2.nc", "GOT5.5/ocean_tides/o1.nc", "GOT5.5/ocean_tides/oo1.nc", "GOT5.5/ocean_tides/p1.nc", "GOT5.5/ocean_tides/q1.nc", "GOT5.5/ocean_tides/s1.nc", "GOT5.5/ocean_tides/s2.nc", "GOT5.5/ocean_tides/sig1.nc"], "type": "z", "variable": "tide_ocean", "version": "5.6", "scale": 0.01, "compressed": false, "reference": "https://doi.org/10.1126/sciadv.abd4744"} \ No newline at end of file diff --git a/test/model_GOT5.6_load.json b/test/model_GOT5.6_load.json new file mode 100644 index 00000000..90fb7e6c --- /dev/null +++ b/test/model_GOT5.6_load.json @@ -0,0 +1 @@ +{"format": "GOT-netcdf", "name": "GOT5.6", "model_file": ["GOT5.5/load_tides/2n2.nc", "GOT5.5/load_tides/j1.nc", "GOT5.5/load_tides/k1.nc", "GOT5.5/load_tides/k2.nc", "GOT5.6/load_tides/l2.nc", "GOT5.6/load_tides/m1.nc", "GOT5.5/load_tides/m2.nc", "GOT5.6/load_tides/m3.nc", "GOT5.5/load_tides/m4.nc", "GOT5.5/load_tides/ms4.nc", "GOT5.5/load_tides/mu2.nc", "GOT5.6/load_tides/n2.nc", "GOT5.5/load_tides/o1.nc", "GOT5.5/load_tides/oo1.nc", "GOT5.5/load_tides/p1.nc", "GOT5.5/load_tides/q1.nc", "GOT5.5/load_tides/s1.nc", "GOT5.5/load_tides/s2.nc", "GOT5.5/load_tides/sig1.nc"], "type": "z", "variable": "tide_load", "version": "5.6", "scale": 0.001, "compressed": false, "reference": "https://doi.org/10.1126/sciadv.abd4744"} \ No newline at end of file diff --git a/test/model_TPXO9-atlas-v5.json b/test/model_TPXO9-atlas-v5.json index 7dcf755e..404d42a4 100644 --- a/test/model_TPXO9-atlas-v5.json +++ b/test/model_TPXO9-atlas-v5.json @@ -1 +1 @@ -{"format": "netcdf", "name": "TPXO9-atlas-v5", "model_file": ["TPXO9_atlas_v5/h_2n2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_k1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_k2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_m2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_m4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_mf_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_mm_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_mn4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_ms4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_n2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_o1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_p1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_q1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_s1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_s2_tpxo9_atlas_30_v5.nc"], "grid_file": "TPXO9_atlas_v5/grid_tpxo9_atlas_30_v5.nc", "type": "z", "variable": "tide_ocean", "version": "v5", "scale": 0.01, "compressed": false, "reference": "https://www.tpxo.net/global/tpxo9-atlas"} \ No newline at end of file +{"format": "ATLAS-netcdf", "name": "TPXO9-atlas-v5", "model_file": ["TPXO9_atlas_v5/h_2n2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_k1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_k2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_m2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_m4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_mf_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_mm_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_mn4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_ms4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_n2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_o1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_p1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_q1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_s1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/h_s2_tpxo9_atlas_30_v5.nc"], "grid_file": "TPXO9_atlas_v5/grid_tpxo9_atlas_30_v5.nc", "type": "z", "variable": "tide_ocean", "version": "v5", "scale": 0.01, "compressed": false, "reference": "https://www.tpxo.net/global/tpxo9-atlas"} \ No newline at end of file diff --git a/test/model_TPXO9-atlas-v5_currents.json b/test/model_TPXO9-atlas-v5_currents.json index 04bdaa03..ed762762 100644 --- a/test/model_TPXO9-atlas-v5_currents.json +++ b/test/model_TPXO9-atlas-v5_currents.json @@ -1 +1 @@ -{"format": "netcdf", "name": "TPXO9-atlas-v5", "model_file": {"u": ["TPXO9_atlas_v5/u_2n2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_k1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_k2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_m2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_m4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_mf_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_mm_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_mn4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_ms4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_n2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_o1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_p1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_q1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_s1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_s2_tpxo9_atlas_30_v5.nc"], "v": ["TPXO9_atlas_v5/u_2n2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_k1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_k2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_m2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_m4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_mf_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_mm_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_mn4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_ms4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_n2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_o1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_p1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_q1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_s1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_s2_tpxo9_atlas_30_v5.nc"]}, "grid_file": "TPXO9_atlas_v5/grid_tpxo9_atlas_30_v5.nc", "type": ["u", "v"], "version": "v5", "scale": 0.01, "compressed": false, "reference": "https://www.tpxo.net/global/tpxo9-atlas"} \ No newline at end of file +{"format": "ATLAS-netcdf", "name": "TPXO9-atlas-v5", "model_file": {"u": ["TPXO9_atlas_v5/u_2n2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_k1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_k2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_m2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_m4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_mf_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_mm_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_mn4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_ms4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_n2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_o1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_p1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_q1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_s1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_s2_tpxo9_atlas_30_v5.nc"], "v": ["TPXO9_atlas_v5/u_2n2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_k1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_k2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_m2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_m4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_mf_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_mm_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_mn4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_ms4_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_n2_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_o1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_p1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_q1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_s1_tpxo9_atlas_30_v5.nc", "TPXO9_atlas_v5/u_s2_tpxo9_atlas_30_v5.nc"]}, "grid_file": "TPXO9_atlas_v5/grid_tpxo9_atlas_30_v5.nc", "type": ["u", "v"], "version": "v5", "scale": 0.01, "compressed": false, "reference": "https://www.tpxo.net/global/tpxo9-atlas"} \ No newline at end of file diff --git a/test/test_atlas_read.py b/test/test_atlas_read.py index a5c6debb..cd758c4b 100644 --- a/test/test_atlas_read.py +++ b/test/test_atlas_read.py @@ -92,7 +92,7 @@ def download_TPXO9_v2(aws_access_key_id,aws_secret_access_key,aws_region_name): bucket = s3.Bucket('pytmd') # model parameters for TPXO9-atlas-v2 - model = pyTMD.io.model(filepath,format='netcdf',compressed=True, + model = pyTMD.io.model(filepath,format='ATLAS-netcdf',compressed=True, verify=False).elevation('TPXO9-atlas-v2') # recursively create model directory model.model_directory.mkdir(parents=True, exist_ok=True) @@ -234,6 +234,7 @@ def test_compare_TPXO9_v2(METHOD): def test_verify_TPXO8(METHOD, EXTRAPOLATE, CROP): # model parameters for TPXO8-atlas model = pyTMD.io.model(filepath,compressed=False).elevation('TPXO8-atlas') + corrections, _, grid = model.format.partition('-') # constituents for test constituents = ['m2','s2'] @@ -275,7 +276,7 @@ def test_verify_TPXO8(METHOD, EXTRAPOLATE, CROP): amp,ph,D,c = pyTMD.io.OTIS.extract_constants( val['longitude'], val['latitude'], model.grid_file, model.model_file, model.projection, type=model.type, - method=METHOD, extrapolate=EXTRAPOLATE, grid=model.format) + method=METHOD, extrapolate=EXTRAPOLATE, grid=corrections) # delta time deltat = np.zeros_like(val['time']) # calculate complex phase in radians for Euler's @@ -290,7 +291,7 @@ def test_verify_TPXO8(METHOD, EXTRAPOLATE, CROP): # predict tidal elevations at time tide.mask[:] = np.any(hc.mask, axis=1) tide.data[:] = pyTMD.predict.drift(val['time'], hc[:,i], - constituents, deltat=deltat, corrections=model.format) + constituents, deltat=deltat, corrections=corrections) # will verify differences between model outputs are within tolerance eps = 0.03 @@ -316,7 +317,8 @@ def test_verify_TPXO9_v2(METHOD, EXTRAPOLATE, CROP): 'h_k1_tpxo9_atlas_30_v2.nc.gz','h_o1_tpxo9_atlas_30_v2.nc.gz'] model_file = [model_directory.joinpath(m) for m in model_files] constituents = ['m2','s2','k1','o1'] - model_format = 'netcdf' + model_format = 'ATLAS-netcdf' + corrections, _ , grid = model_format.partition('-') TYPE = 'z' SCALE = 1.0/1000.0 GZIP = True @@ -365,7 +367,7 @@ def test_verify_TPXO9_v2(METHOD, EXTRAPOLATE, CROP): # predict tidal elevations at time tide.mask[:] = np.any(hc.mask, axis=1) tide.data[:] = pyTMD.predict.drift(val['time'], hc, c, - deltat=deltat, corrections=model_format) + deltat=deltat, corrections=corrections) # will verify differences between model outputs are within tolerance eps = 0.05 diff --git a/test/test_download_and_read.py b/test/test_download_and_read.py index 15880045..61d39475 100644 --- a/test/test_download_and_read.py +++ b/test/test_download_and_read.py @@ -571,6 +571,7 @@ def test_tidal_ellipse(self): def test_solve(self): # get model parameters model = pyTMD.io.model(filepath).elevation('CATS2008') + corrections, _, grid = model.format.partition('-') # calculate a forecast every minute minutes = np.arange(366*1440) @@ -583,7 +584,7 @@ def test_solve(self): constituents = pyTMD.io.OTIS.read_constants( model.grid_file, model.model_file, model.projection, type=model.type, - grid=model.format) + grid=corrections) c = constituents.fields DELTAT = np.zeros_like(tide_time) @@ -598,7 +599,7 @@ def test_solve(self): hc = amp*np.exp(-1j*ph*np.pi/180.0) # predict tidal elevations at times TIDE = pyTMD.predict.time_series(tide_time, hc, c, - deltat=DELTAT, corrections=model.format) + deltat=DELTAT, corrections=corrections) # solve for amplitude and phase famp, fph = pyTMD.solve.constants(tide_time, TIDE.data, c) # calculate complex form of constituent oscillation diff --git a/test/test_fes_predict.py b/test/test_fes_predict.py index 6ea921e3..fbace2be 100644 --- a/test/test_fes_predict.py +++ b/test/test_fes_predict.py @@ -103,7 +103,8 @@ def test_verify_FES2014(METHOD, CROP): model_file = [model_directory.joinpath(m) for m in model_files] c = ['2n2','k1','k2','m2','m4','mf','mm','msqm','mtm','n2','o1', 'p1','q1','s1','s2'] - model_format = 'FES' + model_format = 'FES-netcdf' + corrections, _ , grid = model_format.partition('-') VERSION = 'FES2014' TYPE = 'z' SCALE = 1.0/100.0 @@ -142,9 +143,9 @@ def test_verify_FES2014(METHOD, CROP): # predict tidal elevations at time and infer minor corrections tide.mask[:] = np.any(hc.mask, axis=1) tide.data[:] = pyTMD.predict.drift(tide_time, hc, c, - deltat=deltat, corrections=model_format) + deltat=deltat, corrections=corrections) minor = pyTMD.predict.infer_minor(tide_time, hc, c, - deltat=deltat, corrections=model_format) + deltat=deltat, corrections=corrections) tide.data[:] += minor.data[:] # will verify differences between model outputs are within tolerance diff --git a/test/test_model.py b/test/test_model.py index 1952a900..f25a8177 100644 --- a/test/test_model.py +++ b/test/test_model.py @@ -80,7 +80,7 @@ def test_definition_FES(file_format): 'mn4','ms4','msf','msqm','mtm','mu2','n2','n4','nu2', 'o1','p1','q1','r2','s1','s2','s4','sa','ssa','t2'] # test read variables - assert m.format == 'FES' + assert m.format == 'FES-netcdf' assert m.name == 'FES2014' # assert that all model files are in the model definition for f in model_files: @@ -231,7 +231,7 @@ def test_definition_FES_currents(file_format): 'mn4','ms4','msf','msqm','mtm','mu2','n2','n4','nu2', 'o1','p1','q1','r2','s1','s2','s4','sa','ssa','t2'] # test read variables - assert m.format == 'FES' + assert m.format == 'FES-netcdf' assert m.name == 'FES2014' # assert that all model files are in the model definition for t in ['u','v']: @@ -367,7 +367,7 @@ def test_definition_GOT(file_format): 'GOT4.10c/grids_loadtide/s1load.d.gz', 'GOT4.10c/grids_loadtide/s2load.d.gz'] # test read variables - assert m.format == 'GOT' + assert m.format == 'GOT-ascii' assert m.name == 'GOT4.10' # assert that all model files are in the model definition for f in model_files: @@ -478,7 +478,7 @@ def test_definition_TPXO9(file_format): 'TPXO9_atlas_v5/h_s2_tpxo9_atlas_30_v5.nc'] grid_file = pathlib.Path('TPXO9_atlas_v5/grid_tpxo9_atlas_30_v5.nc') # test read variables - assert m.format == 'netcdf' + assert m.format == 'ATLAS-netcdf' assert m.name == 'TPXO9-atlas-v5' assert m.grid_file == grid_file # assert that all model files are in the model definition @@ -537,7 +537,7 @@ def test_definition_TPXO9_glob(file_format): local = filepath.joinpath(grid_file) local.touch(exist_ok=True) # test read variables - assert m.format == 'netcdf' + assert m.format == 'ATLAS-netcdf' assert m.name == 'TPXO9-atlas-v5' # create model definition file fid = io.StringIO() @@ -620,7 +620,7 @@ def test_definition_TPXO9_currents(file_format): 'TPXO9_atlas_v5/u_s2_tpxo9_atlas_30_v5.nc'] grid_file = pathlib.Path('TPXO9_atlas_v5/grid_tpxo9_atlas_30_v5.nc') # test read variables - assert m.format == 'netcdf' + assert m.format == 'ATLAS-netcdf' assert m.name == 'TPXO9-atlas-v5' assert m.grid_file == grid_file for t in ['u','v']: diff --git a/test/test_perth3_read.py b/test/test_perth3_read.py index d02506f6..007f7cd2 100644 --- a/test/test_perth3_read.py +++ b/test/test_perth3_read.py @@ -93,7 +93,8 @@ def test_verify_GOT47(METHOD, CROP): 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz'] model_file = [model_directory.joinpath(m) for m in model_files] constituents = ['q1','o1','p1','k1','n2','m2','s2','k2','s1'] - model_format = 'GOT' + model_format = 'GOT-ascii' + corrections, _, grid = model_format.partition('-') GZIP = True SCALE = 1.0 @@ -121,7 +122,7 @@ def test_verify_GOT47(METHOD, CROP): # extract amplitude and phase from tide model amp,ph,cons = pyTMD.io.GOT.extract_constants(lon, lat, model_file, - method=METHOD, compressed=GZIP, scale=SCALE, crop=CROP) + grid=grid, method=METHOD, compressed=GZIP, scale=SCALE, crop=CROP) assert all(c in constituents for c in cons) # interpolate delta times from calendar dates to tide time deltat = timescale.time.interpolate_delta_time( @@ -137,9 +138,9 @@ def test_verify_GOT47(METHOD, CROP): # predict tidal elevations at time and infer minor corrections tide.mask[:] = np.any(hc.mask, axis=1) tide.data[:] = pyTMD.predict.drift(tide_time, hc, cons, - deltat=deltat, corrections=model_format) + deltat=deltat, corrections=corrections) minor = pyTMD.predict.infer_minor(tide_time, hc, cons, - deltat=deltat, corrections=model_format) + deltat=deltat, corrections=corrections) tide.data[:] += minor.data[:] # will verify differences between model outputs are within tolerance @@ -161,6 +162,8 @@ def test_compare_GOT47(METHOD): model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz', 'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz'] model_file = [model_directory.joinpath(m) for m in model_files] + model_format = 'GOT-ascii' + corrections, _, grid = model_format.partition('-') GZIP = True SCALE = 1.0 @@ -178,14 +181,14 @@ def test_compare_GOT47(METHOD): # extract amplitude and phase from tide model amp1, ph1, c1 = pyTMD.io.GOT.extract_constants(lon, lat, model_file, - method=METHOD, compressed=GZIP, scale=SCALE) + grid=grid, method=METHOD, compressed=GZIP, scale=SCALE) # calculate complex form of constituent oscillation hc1 = amp1*np.exp(-1j*ph1*np.pi/180.0) # read and interpolate constituents from tide model constituents = pyTMD.io.GOT.read_constants(model_file, compressed=GZIP) amp2, ph2 = pyTMD.io.GOT.interpolate_constants(lon, lat, - constituents, method=METHOD, scale=SCALE) + constituents, grid=grid, method=METHOD, scale=SCALE) # calculate complex form of constituent oscillation hc2 = amp2*np.exp(-1j*ph2*np.pi/180.0)