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
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) routinesio.model.py
: retrieves tide model parameters for named tide modelsio.OTIS.py
: extract tidal harmonic constants from OTIS tide modelsio.ATLAS.py
: extract tidal harmonic constants from ATLAS netcdf modelsio.GOT.py
: extract tidal harmonic constants from GOT tide modelsio.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
import numpy as np
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'
TMDwidgets.VBox([
TMDwidgets.directory,
TMDwidgets.model,
TMDwidgets.compress
])
Setup tide model parameters
# get model parameters
model = pyTMD.io.model(TMDwidgets.directory.value,
compressed=TMDwidgets.compress.value
).elevation(TMDwidgets.model.value)
Setup coordinates for calculating tides
# create a global image
xlimits = [-180,180]
ylimits = [-90, 90]
spacing = [0.25, 0.25]
# 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)
# x and y dimensions
nx = int((xlimits[1]-xlimits[0])/spacing[0])+1
ny = int((ylimits[1]-ylimits[0])/spacing[1])+1
# flatten latitude and longitude to arrays
lon,lat = xgrid.flatten(), ygrid.flatten()
Calculate tidal amplitudes and phases
# read tidal constants and interpolate to grid points
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, crop=True,
method='spline', grid=model.file_format)
elif (model.format == 'ATLAS-netcdf'):
amp,ph,D,c = pyTMD.io.ATLAS.extract_constants(lon, lat, model.grid_file,
model.model_file, type=model.type, crop=True, method='spline',
scale=model.scale, compressed=model.compressed)
elif model.format in ('GOT-ascii', 'GOT-netcdf'):
amp,ph,c = pyTMD.io.GOT.extract_constants(lon, lat, model.model_file,
grid=model.file_format, crop=True, method='spline',
scale=model.scale, compressed=model.compressed)
elif (model.format == 'FES-netcdf'):
amp,ph = pyTMD.io.FES.extract_constants(lon, lat, model.model_file,
type=model.type, version=model.version, crop=True,
method='spline', scale=model.scale, compressed=model.compressed)
c = model.constituents
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)
# find constituents for tidal form factors
k1 = c.index('k1')
o1 = c.index('o1')
m2 = c.index('m2')
s2 = c.index('s2')
n2 = c.index('n2')
# select form factor
if TMDwidgets.form_factor.value == 'Courtier':
# tidal form factor from Courtier
factor = np.reshape((amp[:,k1] + amp[:,o1])/(amp[:,m2] + amp[:,s2]), (ny,nx))
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 = np.reshape((amp[:,m2] + amp[:,n2])/(amp[:,m2] + amp[:,s2]), (ny,nx))
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])
im = ax.imshow(factor, interpolation='nearest',
norm=norm, cmap='plasma', transform=projection,
extent=extent, origin='lower')
# add high resolution cartopy coastlines
ax.coastlines('10m')
# 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(im, 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)
# 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()