{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Plot Ross Ice Shelf Map\n", "=======================\n", "\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", "- 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", "\n", "Global Tide Model (GOT) solutions provided by Richard Ray at GSFC \n", "\n", "Finite Element Solution (FES) provided by AVISO \n", "- https://www.aviso.altimetry.fr/en/data/products/auxiliary-products/global-tide-fes.html\n", "\n", "#### Python Dependencies\n", " - [numpy: Scientific Computing Tools For Python](https://www.numpy.org) \n", " - [scipy: Scientific Tools for Python](https://www.scipy.org/) \n", " - [pyproj: Python interface to PROJ library](https://pypi.org/project/pyproj/) \n", " - [netCDF4: Python interface to the netCDF C library](https://unidata.github.io/netcdf4-python/) \n", " - [matplotlib: Python 2D plotting library](http://matplotlib.org/) \n", " - [cartopy: Python package designed for geospatial data processing](https://scitools.org.uk/cartopy/docs/latest/) \n", "\n", "#### Program Dependencies\n", "\n", "- `calc_astrol_longitudes.py`: computes the basic astronomical mean longitudes \n", "- `convert_ll_xy.py`: convert lat/lon points to and from projected coordinates \n", "- `load_constituent.py`: loads parameters for a given tidal constituent \n", "- `load_nodal_corrections.py`: load the nodal corrections for tidal constituents \n", "- `io.model.py`: retrieves tide model parameters for named tide models\n", "- `io.OTIS.py`: extract tidal harmonic constants from OTIS tide models \n", "- `io.ATLAS.py`: extract tidal harmonic constants from ATLAS netcdf models \n", "- `io.FES.py`: extract tidal harmonic constants from FES tide models \n", "- `predict.py`: predict tidal values using harmonic constants \n", "- `time.py`: utilities for calculating time operations\n", "- `utilities.py`: download and management utilities for files\n", "\n", "This notebook uses Jupyter widgets to set parameters for calculating the tidal maps. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Load modules" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\n", "import pyproj\n", "import datetime\n", "import numpy as np\n", "import matplotlib\n", "matplotlib.rcParams['axes.linewidth'] = 2.0\n", "matplotlib.rcParams[\"animation.html\"] = \"jshtml\"\n", "import matplotlib.pyplot as plt\n", "import matplotlib.animation as animation\n", "import cartopy.crs as ccrs\n", "import ipywidgets as widgets\n", "from IPython.display import HTML\n", "\n", "# import tide programs\n", "import pyTMD.io\n", "import pyTMD.time\n", "import pyTMD.predict\n", "import pyTMD.tools\n", "import pyTMD.utilities\n", "\n", "# autoreload\n", "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Set parameters for program\n", "\n", "- Model directory \n", "- Tide model \n", "- Date to run " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# available model list\n", "model_list = sorted(pyTMD.io.model.global_ocean() + pyTMD.io.model.antarctic_ocean())\n", "# display widgets for setting directory and model\n", "TMDwidgets = pyTMD.tools.widgets()\n", "TMDwidgets.model.options = model_list\n", "TMDwidgets.model.value = 'GOT4.10'\n", "widgets.VBox([\n", " TMDwidgets.directory,\n", " TMDwidgets.model,\n", " TMDwidgets.atlas,\n", " TMDwidgets.compress,\n", " TMDwidgets.datepick\n", "])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Setup tide model parameters" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# get model parameters\n", "model = pyTMD.io.model(TMDwidgets.directory.value,\n", " format=TMDwidgets.atlas.value,\n", " compressed=TMDwidgets.compress.value\n", " ).elevation(TMDwidgets.model.value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Setup coordinates for calculating tides" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# create an image around the Ross Ice Shelf\n", "xlimits = [-740000,520000]\n", "ylimits = [-1430000,-300000]\n", "spacing = [5e3,-5e3]\n", "# x and y coordinates\n", "x = np.arange(xlimits[0],xlimits[1]+spacing[0],spacing[0])\n", "y = np.arange(ylimits[1],ylimits[0]+spacing[1],spacing[1])\n", "xgrid,ygrid = np.meshgrid(x,y)\n", "# x and y dimensions\n", "nx = int((xlimits[1]-xlimits[0])/spacing[0])+1\n", "ny = int((ylimits[0]-ylimits[1])/spacing[1])+1\n", "# convert image coordinates from polar stereographic to latitude/longitude\n", "crs1 = pyproj.CRS.from_epsg(3031)\n", "crs2 = pyproj.CRS.from_epsg(4326)\n", "transformer = pyproj.Transformer.from_crs(crs1, crs2, always_xy=True)\n", "lon,lat = transformer.transform(xgrid.flatten(), ygrid.flatten())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Calculate tide map" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# convert from calendar date to days relative to Jan 1, 1992 (48622 MJD)\n", "YMD = TMDwidgets.datepick.value\n", "tide_time = pyTMD.time.convert_calendar_dates(YMD.year, YMD.month,\n", " YMD.day, hour=np.arange(24))\n", "# delta time (TT - UT1) file\n", "delta_file = pyTMD.utilities.get_data_path(['data','merged_deltat.data'])\n", "\n", "# read tidal constants and interpolate to grid points\n", "if model.format in ('OTIS','ATLAS','ESR'):\n", " amp,ph,D,c = pyTMD.io.OTIS.extract_constants(lon, lat, model.grid_file,\n", " model.model_file, model.projection, type=model.type,\n", " method='spline', grid=model.format)\n", " DELTAT = np.zeros_like(tide_time)\n", "elif (model.format == 'netcdf'):\n", " amp,ph,D,c = pyTMD.io.ATLAS.extract_constants(lon, lat, model.grid_file,\n", " model.model_file, type=model.type, method='spline',\n", " scale=model.scale, compressed=model.compressed)\n", " DELTAT = np.zeros_like(tide_time)\n", "elif (model.format == 'GOT'):\n", " amp,ph,c = pyTMD.io.GOT.extract_constants(lon, lat, model.model_file,\n", " method='spline', scale=model.scale,\n", " compressed=model.compressed)\n", " # interpolate delta times from calendar dates to tide time\n", " DELTAT = pyTMD.time.interpolate_delta_time(delta_file, tide_time)\n", "elif (model.format == 'FES'):\n", " amp,ph = pyTMD.io.FES.extract_constants(lon, lat, model.model_file,\n", " type=model.type, version=model.version, method='spline',\n", " scale=model.scale, compressed=model.compressed)\n", " c = model.constituents\n", " # interpolate delta times from calendar dates to tide time\n", " DELTAT = pyTMD.time.interpolate_delta_time(delta_file, tide_time)\n", " \n", "# calculate complex phase in radians for Euler's\n", "cph = -1j*ph*np.pi/180.0\n", "# calculate constituent oscillation\n", "hc = amp*np.exp(cph)\n", " \n", "# allocate for tide map calculated every hour\n", "tide_cm = np.ma.zeros((ny,nx,24))\n", "for hour in range(24):\n", " # predict tidal elevations at time and infer minor corrections\n", " TIDE = pyTMD.predict.map(tide_time[hour], hc, c, deltat=DELTAT[hour],\n", " corrections=model.format)\n", " MINOR = pyTMD.predict.infer_minor(tide_time[hour], hc, c,\n", " deltat=DELTAT[hour], corrections=model.format)\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))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Create animation of hourly tidal oscillation" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# output Ross Ice Shelf Tide Animation\n", "projection = ccrs.Stereographic(central_longitude=0.0,\n", " central_latitude=-90.0,true_scale_latitude=-71.0)\n", "fig, ax = plt.subplots(num=1, figsize=(9,8),\n", " subplot_kw=dict(projection=projection))\n", "# plot tide height\n", "vmin,vmax = (np.min(tide_cm), np.max(tide_cm))\n", "extent = (xlimits[0],xlimits[1],ylimits[0],ylimits[1])\n", "im = ax.imshow(np.zeros((ny,nx)), interpolation='nearest',\n", " vmin=vmin, vmax=vmax, transform=projection,\n", " extent=extent, origin='upper', animated=True)\n", "# add high resolution cartopy coastlines\n", "ax.coastlines('10m')\n", "\n", "# Add colorbar and adjust size\n", "# pad = distance from main plot axis\n", "# extend = add extension triangles to upper and lower bounds\n", "# options: neither, both, min, max\n", "# shrink = percent size of colorbar\n", "# aspect = lengthXwidth aspect of colorbar\n", "cbar = plt.colorbar(im, ax=ax, pad=0.025, extend='both',\n", " extendfrac=0.0375, shrink=0.85, aspect=22.5, drawedges=False)\n", "# rasterized colorbar to remove lines\n", "cbar.solids.set_rasterized(True)\n", "# Add label to the colorbar\n", "cbar.ax.set_ylabel(f'{model.name} Tide Height', fontsize=13)\n", "cbar.ax.set_xlabel('cm', fontsize=13)\n", "cbar.ax.xaxis.set_label_coords(0.50, 1.04)\n", "# ticks lines all the way across\n", "cbar.ax.tick_params(which='both', width=1, length=18,\n", " labelsize=13, direction='in')\n", "# add title (date and time)\n", "ttl = ax.set_title(None, fontsize=13)\n", "# set x and y limits\n", "ax.set_xlim(xlimits)\n", "ax.set_ylim(ylimits)\n", "\n", "# stronger linewidth on frame\n", "ax.spines['geo'].set_linewidth(2.0)\n", "ax.spines['geo'].set_capstyle('projecting')\n", "# adjust subplot within figure\n", "fig.subplots_adjust(left=0.02,right=0.98,bottom=0.05,top=0.98)\n", " \n", "# animate each map\n", "def animate_maps(hour):\n", " # set map data\n", " im.set_data(tide_cm[:,:,hour])\n", " # set title\n", " args = (YMD.year,YMD.month,YMD.day,hour)\n", " ttl.set_text('{0:4d}-{1:02d}-{2:02d}T{3:02d}:00:00'.format(*args))\n", "\n", "# set animation\n", "anim = animation.FuncAnimation(fig, animate_maps, frames=24)\n", "%matplotlib inline\n", "HTML(anim.to_jshtml())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "interpreter": { "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" }, "kernelspec": { "display_name": "Python 3.8.10 64-bit", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0]" } }, "nbformat": 4, "nbformat_minor": 4 }