#!/usr/bin/env python # coding: utf-8 # Check Tide Map # ============== # # Check if a given point is within a tide model domain # # OTIS format tidal solutions provided by Ohio 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/ # # Global Tide Model (GOT) solutions provided by Richard Ray at GSFC # # Finite Element Solution (FES) provided by AVISO # - https://www.aviso.altimetry.fr/en/data/products/auxiliary-products/global-tide-fes.html # # #### Python Dependencies # - [numpy: Scientific Computing Tools For Python](https://www.numpy.org) # - [scipy: Scientific Tools for Python](https://www.scipy.org/) # - [pyproj: Python interface to PROJ library](https://pypi.org/project/pyproj/) # - [netCDF4: Python interface to the netCDF C library](https://unidata.github.io/netcdf4-python/) # - [matplotlib: Python 2D plotting library](https://matplotlib.org/) # - [ipyleaflet: Jupyter / Leaflet bridge enabling interactive maps](https://github.com/jupyter-widgets/ipyleaflet) # # #### Program Dependencies # # - `convert_ll_xy.py`: convert lat/lon points to and from projected coordinates # - `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 # - `convert_ll_xy.py`: converts lat/lon points to and from projected coordinates # # This notebook uses Jupyter widgets to set parameters for calculating the tidal maps. # #### Load modules # In[ ]: from __future__ import print_function import os import numpy as np import matplotlib.pyplot as plt import ipywidgets as widgets import IPython.display # import tide programs import pyTMD.io import pyTMD.time import pyTMD.tools import pyTMD.convert_ll_xy # autoreload get_ipython().run_line_magic('load_ext', 'autoreload') get_ipython().run_line_magic('autoreload', '2') # In[ ]: # 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' widgets.VBox([ TMDwidgets.directory, TMDwidgets.model, TMDwidgets.atlas, TMDwidgets.compress ]) # In[ ]: # 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 # In[ ]: # get model parameters model = pyTMD.io.model(TMDwidgets.directory.value, format=TMDwidgets.atlas.value, compressed=TMDwidgets.compress.value ).elevation(TMDwidgets.model.value) # read tidal constants and interpolate to grid points if model.format in ('OTIS','ATLAS','ESR'): # if reading a single OTIS solution xi,yi,hz,mz,iob,dt = pyTMD.io.OTIS.read_otis_grid(model.grid_file) elif (model.format == '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'): # 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 == 'FES'): # 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) # In[ ]: 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','ESR'): # 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.convert_ll_xy(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 == '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 == 'GOT'): # 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'): # 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) # In[ ]: get_ipython().run_line_magic('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) # In[ ]: