Check Tide Map

This (notebook) demonstrates checking if given points are within a tide model domain

OTIS format tidal solutions provided by Oregon State University and ESR

Global Tide Model (GOT) solutions provided by Richard Ray at GSFC

Finite Element Solution (FES) provided by AVISO

Python Dependencies

Program Dependencies

  • crs.py: Coordinate Reference System (CRS) routines

  • io.model.py: retrieves tide model parameters for named tide models

  • io.OTIS.py: extract tidal harmonic constants from OTIS tide models

  • io.ATLAS.py: extract tidal harmonic constants from netcdf models

  • io.GOT.py: extract tidal harmonic constants from GSFC GOT models

  • io.FES.py: extract tidal harmonic constants from FES tide models

This notebook uses Jupyter widgets to set parameters for calculating the tidal maps.

Load modules

from __future__ import print_function

import numpy as np
import matplotlib.pyplot as plt
import IPython.display

# import tide programs
import pyTMD.crs
import pyTMD.io
import pyTMD.time
import pyTMD.tools
# autoreload
%load_ext autoreload
%autoreload 2

Set parameters for program

  • Model directory

  • Tide model

# available model list
model_list = sorted(pyTMD.io.model.ocean_elevation())
# display widgets for setting directory and model
TMDwidgets = pyTMD.tools.widgets()
TMDwidgets.model.options = model_list
TMDwidgets.model.value = 'GOT4.10'
TMDwidgets.VBox([
    TMDwidgets.directory,
    TMDwidgets.model,
    TMDwidgets.compress
])

Select location to check

# default coordinates to use
LAT,LON = (32.86710263,-117.25750387)
m = pyTMD.tools.leaflet(center=(LAT,LON), zoom=12,
    zoom_control=True, marker_control=True)
# show map
m.map

Read and create mask of valid model values

# get model parameters
model = pyTMD.io.model(TMDwidgets.directory.value,
    compressed=TMDwidgets.compress.value
   ).elevation(TMDwidgets.model.value)

# read tidal constants and interpolate to grid points
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(model.grid_file)
elif model.format in ('ATLAS-netcdf',):
    # if reading a netCDF OTIS atlas solution
    xi,yi,hz = pyTMD.io.ATLAS.read_netcdf_grid(model.grid_file,
        compressed=model.compressed, type='z')
    # invert bathymetry mask
    mz = np.invert(hz.mask)
elif (model.format == 'GOT-ascii'):
    # if reading a NASA GOT solution
    hc,xi,yi,c = pyTMD.io.GOT.read_ascii_file(model.model_file[0],
        compressed=model.compressed)
    # invert tidal constituent mask
    mz = np.invert(hc.mask)
elif (model.format == 'GOT-netcdf'):
    # if reading a NASA GOT netcdf solution
    hc,xi,yi,c = pyTMD.io.GOT.read_netcdf_file(model.model_file[0],
        compressed=model.compressed)
    # invert tidal constituent mask
    mz = np.invert(hc.mask)
elif (model.format == 'FES-netcdf'):
    # if reading a FES netCDF solution
    hc,xi,yi = pyTMD.io.FES.read_netcdf_file(model.model_file[0],
        compressed=model.compressed, type='z', version=model.version)
    # invert tidal constituent mask
    mz = np.invert(hc.mask)
def update_coordinates(sender):
    # leaflet location
    LAT,LON = np.copy(m.marker.location)
    # verify longitudes
    LON = m.wrap_longitudes(LON)
    # adjust dimensions of input coordinates to be iterable
    LON = np.atleast_1d(LON)
    LAT = np.atleast_1d(LAT)
    # read tidal constants and interpolate to grid points
    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(model.grid_file)
        # convert coordinate systems of input latitude and longitude
        x,y = pyTMD.crs().convert(np.atleast_1d(LON), np.atleast_1d(LAT),
            model.projection, 'F')
        # adjust longitudinal convention of input latitude and longitude
        # to fit tide model convention (if global)
        if (np.min(x) < np.min(xi)) & (model.projection == '4326'):
            lt0, = np.nonzero(x < 0)
            x[lt0] += 360.0
        if (np.max(x) > np.max(xi)) & (model.projection == '4326'):
            gt180, = np.nonzero(x > 180)
            x[gt180] -= 360.0
    elif (model.format == 'ATLAS-netcdf'):
        # if reading a netCDF OTIS atlas solution
        # adjust longitudinal convention of input latitude and longitude
        # to fit tide model convention
        x,y = np.copy([LON,LAT]).astype(np.float64)
        lt0, = np.nonzero(x < 0)
        x[lt0] += 360.0
    elif model.format in ('GOT-ascii', 'GOT-netcdf'):
        # if reading a NASA GOT solution
        # adjust longitudinal convention of input latitude and longitude
        # to fit tide model convention
        x,y = np.copy([LON,LAT]).astype(np.float64)
        lt0, = np.nonzero(x < 0)
        x[lt0] += 360.0
    elif (model.format == 'FES-netcdf'):
        # if reading a FES netCDF solution
        # adjust longitudinal convention of input latitude and longitude
        # to fit tide model convention
        x,y = np.copy([LON,LAT]).astype(np.float64)
        lt0, = np.nonzero(x < 0)
        x[lt0] += 360.0
    # update plot coordinates
    m.point.set_xdata(x)
    m.point.set_ydata(y)
    # refresh plot
    IPython.display.display(m.figure)

Plot mask and selected location

%matplotlib widget
# check coordinates on tide grid
m.figure,ax = plt.subplots(num=1, figsize=(8.25,5.25))
ax.imshow(mz, interpolation='nearest',
    extent=(xi.min(),xi.max(),yi.min(),yi.max()),
    origin='lower', cmap='gray')
m.point, = ax.plot([],[],'r*')
update_coordinates(None)
# no ticks on the x and y axes
ax.get_xaxis().set_ticks([])
ax.get_yaxis().set_ticks([])
# stronger linewidth on frame
[i.set_linewidth(2.0) for i in ax.spines.values()]
# adjust subplot within figure
m.figure.tight_layout()
IPython.display.clear_output(wait=True)
m.marker.observe(update_coordinates)