{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# NCL_panel_5.py\nThis script illustrates the following concepts:\n   - Paneling three plots vertically on a page\n   - Adding a common title to subplots\n   - Adding a common colorbar to subplots\n   - Adding figure label to subplots\n   - Adding text to subplots\n   - Truncating a color map\n\nSee following URLs to see the reproduced NCL plot & script:\n    - Original NCL script: https://www.ncl.ucar.edu/Applications/Scripts/panel_5.ncl\n    - Original NCL plot: https://www.ncl.ucar.edu/Applications/Images/panel_5_lg.png\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Import packages:\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import cartopy.crs as ccrs\nfrom cartopy.mpl.gridliner import LongitudeFormatter, LatitudeFormatter\nimport matplotlib.pyplot as plt\nfrom mpl_toolkits.axes_grid1.inset_locator import inset_axes\nimport numpy as np\nimport xarray as xr\n\nimport geocat.datafiles as gdf\nfrom geocat.viz import cmaps as gvcmaps\nimport geocat.viz.util as gvutil"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Read in data:\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Open a netCDF data file using xarray default engine and load the data into\n# xarrays, choosing the 2nd timestamp\nds = xr.open_dataset(gdf.get(\"netcdf_files/uv300.nc\")).isel(time=1)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Utility Function: Labelled Filled Contour Plot:\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Define a utility plotting function in order not to repeat many lines of codes\n# since we need to make the same figure with two different variables.\n\n\ndef plot_labelled_filled_contours(data, ax=None, label=None):\n    \"\"\"\n    A utility function for convenience that plots labelled, filled contours with black contours\n    marking each level.It will return a dictionary containing three objects corresponding to the\n    filled contours, the black contours, and the contour labels.\n    \"\"\"\n\n    # Import an NCL colormap, truncating it by using geocat.viz.util convenience function\n    newcmp = gvutil.truncate_colormap(gvcmaps.gui_default,\n                                      minval=0.03,\n                                      maxval=0.9)\n\n    handles = dict()\n    handles[\"filled\"] = data.plot.contourf(\n        ax=ax,  # this is the axes we want to plot to\n        cmap=newcmp,  # our special colormap\n        levels=levels,  # contour levels specified outside this function\n        transform=projection,  # data projection\n        add_colorbar=False,  # don't add individual colorbars for each plot call\n        add_labels=False,  # turn off xarray's automatic Lat, lon labels\n    )\n\n    # matplotlib's contourf doesn't let you specify the \"edgecolors\" (MATLAB terminology)\n    # instead we plot black contours on top of the filled contours\n    handles[\"contour\"] = data.plot.contour(\n        ax=ax,\n        levels=levels,\n        colors=\"black\",  # note plurals in this and following kwargs\n        linestyles=\"-\",\n        linewidths=0.5,\n        add_labels=False,  # again turn off automatic labels\n    )\n\n    # Label the contours\n    ax.clabel(\n        handles[\"contour\"],\n        fontsize=8,\n        fmt=\"%.0f\",  # Turn off decimal points\n    )\n\n    # Add coastlines and make them semitransparent for plot legibility\n    ax.coastlines(linewidth=0.5, alpha=0.75)\n\n    # Use geocat.viz.util convenience function to set axes tick values\n    gvutil.set_axes_limits_and_ticks(ax,\n                                     xticks=np.arange(-180, 181, 30),\n                                     yticks=np.arange(-90, 91, 30))\n\n    # Use geocat.viz.util convenience function to add minor and major tick lines\n    gvutil.add_major_minor_ticks(ax, labelsize=8)\n\n    # Use geocat.viz.util convenience function to make plots look like NCL plots by using latitude, longitude tick labels\n    gvutil.add_lat_lon_ticklabels(ax)\n    # Remove degree symbol from tick labels\n    ax.yaxis.set_major_formatter(LatitudeFormatter(degree_symbol=''))\n    ax.xaxis.set_major_formatter(LongitudeFormatter(degree_symbol=''))\n\n    # Use geocat.viz.util convenience function to add main title as well as titles to left and right of the plot axes.\n    gvutil.set_titles_and_labels(ax,\n                                 lefttitle=data.attrs['long_name'],\n                                 lefttitlefontsize=10,\n                                 righttitle=data.attrs['units'],\n                                 righttitlefontsize=10)\n\n    # Add a label in the upper left of the axes\n    ax.text(0.025,\n            0.9,\n            label,\n            transform=ax.transAxes,\n            bbox=dict(boxstyle='square, pad=0.25', facecolor='white'))\n    return handles"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Plot:\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Make three panels (i.e. subplots in matplotlib) specifying white space\n# between them using gridspec_kw and hspace\n# Generate figure and axes using Cartopy projection\nprojection = ccrs.PlateCarree()\nfig, ax = plt.subplots(3,\n                       1,\n                       figsize=(6, 10),\n                       gridspec_kw=dict(hspace=0.3),\n                       subplot_kw={\"projection\": projection})\n# Define the contour levels\nlevels = np.linspace(-10, 50, 13)\n\n# Contour-plot U data, save \"handles\" to add a colorbar later\nhandles = plot_labelled_filled_contours(ds.U, ax=ax[0], label='a)')\n\n# Set a common title\nplt.suptitle(\"A common title\", fontsize=16, y=0.94)\n\n# Contour-plot V data\nplot_labelled_filled_contours(ds.V, ax=ax[1], label='b)')\n\n# Contour-plot U data again but in the bottom axes\nplot_labelled_filled_contours(ds.U, ax=ax[2], label='c)')\n\n# Create inset axes for colorbar\ncax = inset_axes(ax[2],\n                 width='100%',\n                 height='7%',\n                 loc='lower left',\n                 bbox_to_anchor=(0, -0.25, 1, 1),\n                 bbox_transform=ax[2].transAxes,\n                 borderpad=0)\n# Add horizontal colorbar\ncbar = plt.colorbar(handles[\"filled\"],\n                    cax=cax,\n                    orientation=\"horizontal\",\n                    ticks=levels[:-1],\n                    drawedges=True,\n                    aspect=30,\n                    extendrect=True,\n                    extendfrac='auto',\n                    shrink=0.8)\ncbar.ax.tick_params(labelsize=10)\n\n# Add figure label underneath subplots\nfig.text(0.5,\n         0.015,\n         \"Figure 1: A nifty panel plot\",\n         horizontalalignment='center',\n         fontsize=14)\n\n# Show the plot\nplt.show()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "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.7.9"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}