Plot Tide Form Factor

This (notebook) demonstrates plotting tidal form factors for classifying tides

  • Daily tidal form factors for determining the dominant species of a region using the classifications from Courtier (1938). The dominant species classifications do have limitations as pointed out by Amin (1986)

  • Monthly tidal form factors for semi-diurnal species from Byun and Hart

Important

Need to download tide model prior to running this notebook.

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

  • 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 ATLAS netcdf models

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

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

Note

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

Load modules

import numpy as np
import xarray as xr
import matplotlib

matplotlib.rcParams["axes.linewidth"] = 2.0
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import cartopy.crs as ccrs
import ipywidgets

# import tide programs
import pyTMD.io
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_nc"
TMDwidgets.VBox(
    [
        TMDwidgets.directory,
        TMDwidgets.model,
    ]
)

Read tide model

# get model parameters
model = pyTMD.io.model(
    TMDwidgets.directory.value,
).from_database(TMDwidgets.model.value)
ds = model.open_dataset(group="z")

Setup coordinates for calculating tides

# create a global image
xlimits = [-180, 180]
ylimits = [-90, 90]
spacing = [1.0, 1.0]
# x and y coordinates
x = np.arange(xlimits[0], xlimits[1] + spacing[0], spacing[0])
y = np.arange(ylimits[0], ylimits[1] + spacing[1], spacing[1])
xgrid, ygrid = np.meshgrid(x, y)
# create xarray DataArrays for coordinates in crs of model
X, Y = ds.tmd.coords_as(xgrid, ygrid, type="grid", crs=4326)

Calculate tidal form factors

Courtier form factor: Ratios between major diurnal tides and major semi-diurnal tides

  • F: < 0.25: Semi-diurnal

  • F: 0.25 - 1.5: Mixed predominantly semi-diurnal

  • F: 1.5 - 3.0: Mixed predominantly diurnal

  • F: > 3.0: Diurnal

Byut-Hart form factor: Ratios between semi-diurnal tides for monthly tidal envelopes

  • E: < 0.8: Spring-Neap

  • E: 0.8 - 1.0: Mixed predominantly Spring-Neap

  • E: 1.0 - 1.15: Mixed predominantly Perigean-Apogean

  • E: > 2.0: Perigean-Apogean

TMDwidgets.form_factor = ipywidgets.Dropdown(
    options=["Courtier", "Byun-Hart"],
    value="Courtier",
    description="Factor:",
    disabled=False,
    style=TMDwidgets.style,
)
display(TMDwidgets.form_factor)
# interpolate model to grid points
ds1 = ds.tmd.interp(X, Y, extrapolate=False)
# calculate amplitudes for form-factor constituents
k1 = ds1["k1"].tmd.amplitude
o1 = ds1["o1"].tmd.amplitude
m2 = ds1["m2"].tmd.amplitude
s2 = ds1["s2"].tmd.amplitude
n2 = ds1["n2"].tmd.amplitude
# select form factor
if TMDwidgets.form_factor.value == "Courtier":
    # tidal form factor from Courtier
    factor = (k1 + o1) / (m2 + s2)
    boundary = np.array([0.0, 0.25, 1.5, 3.0, 5.0])
    ticklabels = ["Semi-Diurnal", "Mixed SD", "Mixed D", "Diurnal"]
    longname = "Tide Species Classification"
elif TMDwidgets.form_factor.value == "Byun-Hart":
    # semi-diurnal form factor from Byun and Hart
    factor = (m2 + n2) / (m2 + s2)
    boundary = np.array([0.0, 0.8, 1.0, 1.15, 2.0])
    ticklabels = ["Spring-Neap", "Mixed S-N", "Mixed P-A", "Perigean-Apogean"]
    longname = "Semi-Diurnal Classification"
# calculate ticks for labels
ticks = 0.5 * (boundary[1:] + boundary[:-1])

Create plot of tidal form factors

# cartopy transform for Equirectangular Projection
projection = ccrs.PlateCarree()
# create figure axis
fig, ax = plt.subplots(
    num=1, figsize=(5.5, 3.5), subplot_kw=dict(projection=projection)
)
# create boundary norm
norm = colors.BoundaryNorm(boundary, ncolors=256)
# plot tidal form factor
extent = (xlimits[0], xlimits[1], ylimits[0], ylimits[1])
sc = factor.plot(
    ax=ax,
    add_colorbar=False,
    add_labels=False,
    norm=norm,
    cmap="plasma",
    transform=projection,
)
# add moderate resolution cartopy coastlines
ax.coastlines("50m")

# Add colorbar and adjust size
# pad = distance from main plot axis
# extend = add extension triangles to upper and lower bounds
# options: neither, both, min, max
# shrink = percent size of colorbar
# aspect = lengthXwidth aspect of colorbar
cbar = plt.colorbar(
    sc,
    ax=ax,
    extend="neither",
    extendfrac=0.0375,
    orientation="horizontal",
    pad=0.025,
    shrink=0.90,
    aspect=22,
    drawedges=False,
)
# rasterized colorbar to remove lines
cbar.solids.set_rasterized(True)
# Add label to the colorbar
cbar.ax.set_title(longname, fontsize=13, rotation=0, y=-2.0, va="top")
# Set the tick levels for the colorbar
cbar.set_ticks(ticks=ticks, labels=ticklabels)
cbar.ax.tick_params(which="both", length=0, labelsize=13)

# axis = equal
ax.set_aspect("equal", adjustable="box")
# set x and y limits
ax.set_xlim(xlimits)
ax.set_ylim(ylimits)

# no ticks on the x and y axes
ax.get_xaxis().set_ticks([])
ax.get_yaxis().set_ticks([])
# stronger linewidth on frame
ax.spines["geo"].set_linewidth(2.0)
ax.spines["geo"].set_capstyle("projecting")

# adjust subplot within figure
fig.subplots_adjust(left=0.02, right=0.98, bottom=0.05, top=0.98)
# show the plot
plt.show()
../_images/be94075c1b566b2b367beb197a6cb216ecb25ae7851e4e13b8b2dfd0e65b2895.png