{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# NCL_panel_3.py\nThis script illustrates the following concepts:\n   - Two panel (subplot) image with shared colorbar and title\n   - Adding a common title to paneled plots\n   - Adding a common colorbar to paneled plots\n   - Importing and truncating a NCL colormap\n\nSee following URLs to see the reproduced NCL plot & script:\n    - Original NCL script: https://www.ncl.ucar.edu/Applications/Scripts/panel_3.ncl\n    - Original NCL plot: https://www.ncl.ucar.edu/Applications/Images/panel_3_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\nimport matplotlib.pyplot as plt\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 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 since we need to make the same figure\n# with two different variables.\n\n\ndef plot_labelled_filled_contours(data, ax=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        xticks=np.arange(-180, 181, 30),  # nice x ticks\n        yticks=np.arange(-90, 91, 30),  # nice y ticks\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\n    ax.coastlines(linewidth=0.5)\n\n    # Use geocat.viz.util convenience function to add minor and major tick lines\n    gvutil.add_major_minor_ticks(ax)\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\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    return handles"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Plot:\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Make two panels (i.e. subplots in matplotlib)\n# Specify ``constrained_layout=True`` to automatically layout panels, colorbars and axes decorations nicely.\n# See https://matplotlib.org/tutorials/intermediate/constrainedlayout_guide.html\n# Generate figure and axes using Cartopy projection\nprojection = ccrs.PlateCarree()\nfig, ax = plt.subplots(2,\n                       1,\n                       constrained_layout=True,\n                       subplot_kw={\"projection\": projection})\n\n# Set figure size (width, height) in inches\nfig.set_size_inches((8, 8.2))\n\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])\n\n# Set a common title\nax[0].set_title(\"A plot with a common colorbar\", fontsize=14, y=1.15)\n\n# Contour-plot V data\nplot_labelled_filled_contours(ds.V, ax=ax[1])\n\n# Add horizontal colorbar\ncbar = plt.colorbar(handles[\"filled\"],\n                    ax=ax,\n                    orientation=\"horizontal\",\n                    ticks=levels[:-1],\n                    drawedges=True,\n                    aspect=30)\ncbar.ax.tick_params(labelsize=10)\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
}