{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# NCL_meteo_1.py\n\nThis script illustrates the following concepts:\n   - Drawing a meteogram\n   - Creating a color map using hex values\n   - Reversing the Y axis\n   - Explicitly setting tickmarks and labels on the bottom X axis\n   - Increasing the thickness of contour lines\n   - Drawing wind barbs\n   - Drawing a bar chart\n   - Changing the width and height of a plot\n   - Overlaying wind barbs and line contours on filled contours\n   - Changing the position of individual plots on a page\n\nSee following URLs to see the reproduced NCL plot & script:\n    - Original NCL script: https://www.ncl.ucar.edu/Applications/Scripts/meteo_1.ncl\n    - Original NCL plot: https://www.ncl.ucar.edu/Applications/Images/meteo_1_lg.png\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Import necessary packages\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import xarray as xr\nimport numpy as np\nfrom matplotlib import pyplot as plt\nfrom matplotlib.colors import ListedColormap, BoundaryNorm\nimport cartopy.crs as ccrs\n\nimport geocat.datafiles as gdf\nfrom geocat.viz import 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 xarray\nds = xr.open_dataset(gdf.get(\"netcdf_files/meteo_data.nc\"), decode_times=False)\n\n# Extract variables from the data\ntempisobar = ds.tempisobar\nlevels = ds.levels\ntaus = ds.taus\nrh = ds.rh\nugrid = ds.ugrid\nvgrid = ds.vgrid\nrain03 = ds.rain03\ntempht = ds.tempht"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Plot:\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Generate figure (set its size (width, height) in inches)\nfig = plt.figure(figsize=(6, 8))\nspec = fig.add_gridspec(ncols=1, nrows=3, height_ratios=[4, 1, 1], hspace=0.4)\n\n# Create axis for contour/wind barb plot\nax1 = fig.add_subplot(spec[0, 0], projection=ccrs.PlateCarree())\n\n# Add coastlines to first axis\nax1.coastlines(linewidths=0.5, alpha=-1)\n\n# Set aspect ratio of the first axis\nax1.set_aspect(2)\n\n# Create a color map with a combination of matplotlib colors and hex values\ncolors = ListedColormap(\n    np.array([\n        'white', 'white', 'white', 'white', 'white', 'mintcream', \"#DAF6D3\",\n        \"#B2FAB9\", \"#B2FAB9\", 'springgreen', 'lime', \"#54A63F\"\n    ]))\ncontour_levels = [-20, -10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]\nnormalized_levels = BoundaryNorm(boundaries=contour_levels, ncolors=12)\n\n# Plot filled contours for the rh variable\ncontour1 = ax1.contourf(rh,\n                        transform=ccrs.PlateCarree(),\n                        cmap=colors,\n                        norm=normalized_levels,\n                        levels=contour_levels,\n                        zorder=2)\n\n# Plot black outlines on top of the filled rh contours\ncontour2 = ax1.contour(rh,\n                       transform=ccrs.PlateCarree(),\n                       colors='black',\n                       levels=contour_levels,\n                       linewidths=0.1,\n                       zorder=3)\n\n# Plot contours for the tempisobar variable\ncontour3 = ax1.contour(tempisobar,\n                       transform=ccrs.PlateCarree(),\n                       colors='red',\n                       levels=[-20, -10, 0, 10, 20, 30, 40, 50, 60],\n                       linewidths=0.7,\n                       linestyles='solid',\n                       zorder=4)\n\n# Create lists of coordinates where the contour labels are going to go\n# Before creating an axes over top of the contour plot, hover your\n# mouse over the locations where you want to plot the contour labels.\n# The coordinate will show up on the bottom right of the figure window.\ncont2Labels = [(1.71, 3.82), (5.49, 3.23), (9.53, 4.34), (9.27, 3.53),\n               (14.08, 4.81), (19.21, 2.24), (17.74, 1.00), (22.23, 3.87),\n               (12.87, 2.54), (10.45, 6.02), (11.51, 4.92)]\n\ncont3Labels = [(7.5, 6.1), (10.0, 4.58), (19.06, 1.91), (8.68, 0.46),\n               (19.52, 4.80), (16.7, 6.07), (8.62, 5.41), (18.53, 5.46)]\n\n# Manually plot contour labels\ncont2labels = ax1.clabel(contour2,\n                         manual=cont2Labels,\n                         fmt='%d',\n                         inline=True,\n                         fontsize=7)\ncont3labels = ax1.clabel(contour3,\n                         manual=cont3Labels,\n                         fmt='%d',\n                         inline=True,\n                         fontsize=7,\n                         colors='black')\n\n# Set contour label backgrounds white\n[\n    txt.set_bbox(dict(facecolor='white', edgecolor='none', pad=.5))\n    for txt in contour2.labelTexts\n]\n[\n    txt.set_bbox(dict(facecolor='white', edgecolor='none', pad=.5))\n    for txt in contour3.labelTexts\n]\n\n# Determine the labels for each tick on the x and y axes\nyticklabels = np.array(levels, dtype=np.int)\nxticklabels = [\n    '12z', '15z', '18z', '21z', 'Apr29', '03z', '06z', '09z', '12z', '15z',\n    '18z', '21z', 'Apr30', '03z', '06z', '09z', '12z', '15z', '18z', '21z',\n    'May01', '03z', '06z', '09z', '12z'\n]\n\n# Make an axis to overlay on top of the contour plot\naxin = fig.add_subplot(spec[0, 0])\n\n# Use the geocat.viz function to set the main title of the plot\ngvutil.set_titles_and_labels(axin,\n                             maintitle='Meteogram for LGSA, 28/12Z',\n                             maintitlefontsize=18,\n                             ylabel='Pressure (mb)',\n                             labelfontsize=12)\n\n# Add a pad between the y axis label and the axis spine\naxin.yaxis.labelpad = 5\n\n# Use the geocat.viz function to set axes limits and ticks\ngvutil.set_axes_limits_and_ticks(axin,\n                                 xlim=[taus[0], taus[-1]],\n                                 ylim=[levels[0], levels[-1]],\n                                 xticks=np.array(taus),\n                                 yticks=np.linspace(1000, 400, 8),\n                                 xticklabels=xticklabels,\n                                 yticklabels=yticklabels)\n\n# Make axis invisible\naxin.patch.set_alpha(0.0)\n\n# Make ticks point inwards\naxin.tick_params(axis=\"x\", direction=\"in\", length=8)\naxin.tick_params(axis=\"y\", direction=\"in\", length=8, labelsize=9)\n\n# Rotate the labels on the x axis so they are vertical\nfor tick in axin.get_xticklabels():\n    tick.set_rotation(90)\n\n# Set aspect ratio of axin so it lines up with axis underneath (ax1)\naxin.set_aspect(0.07)\n\n# Plot wind barbs\nbarbs = axin.barbs(taus,\n                   np.linspace(1000, 400, 8),\n                   ugrid,\n                   vgrid,\n                   color='black',\n                   lw=0.1,\n                   length=5)\n\n# Create text box at lower right of contour plot\nax1.text(1.0,\n         -0.28,\n         \"CONTOUR FROM -20 TO 60 BY 10\",\n         horizontalalignment='right',\n         transform=ax1.transAxes,\n         bbox=dict(boxstyle='square, pad=0.15',\n                   facecolor='white',\n                   edgecolor='black'))\n\n# Create two more axes, one for the bar chart and one for the line graph\naxin1 = fig.add_subplot(spec[1, 0])\naxin2 = fig.add_subplot(spec[2, 0])\n\n# Plot bar chart\n\n# Plot bars depicting the rain03 variable\naxin1.bar(taus, rain03, width=3, color='limegreen', edgecolor='black', linewidth=.2)\n\n# Use the geocat.viz function to set the y axis label\ngvutil.set_titles_and_labels(axin1, ylabel='3hr rain total', labelfontsize=12)\n\n# Determine the labels for each tick on the x and y axes\nyticklabels = ['0.0', '0.10', '0.20', '0.30', '0.40', '0.50']\nxticklabels = [\n    '12z', '', '18z', '', 'Apr29', '', '06z', '', '12z', '', '18z', '', 'Apr30',\n    '', '06z', '', '12z', '', '18z', '', 'May01', '', '06z', '', '12z'\n]\n\n# Use the geocat.viz function to set axes limits and ticks\ngvutil.set_axes_limits_and_ticks(axin1,\n                                 xlim=[0, 72],\n                                 ylim=[0, .5],\n                                 xticks=np.arange(0, 75, 3),\n                                 yticks=np.arange(0, .6, 0.1),\n                                 xticklabels=xticklabels,\n                                 yticklabels=yticklabels)\n\n# Use the geocat.viz function to add minor ticks\ngvutil.add_major_minor_ticks(axin1, y_minor_per_major=5, labelsize=\"small\")\n\n# Make ticks only show up on bottom, right, and left of inset axis\naxin1.tick_params(bottom=True, left=True, right=True, top=False)\naxin1.tick_params(which='minor', top=False, bottom=False)\n\n# Plot line chart\n\n# Plot lines depicting the tempht variable\naxin2.plot(taus, tempht, color='red')\n\n# Use the geocat.viz function to set the y axis label\ngvutil.set_titles_and_labels(axin2, ylabel='Temp at 2m', labelfontsize=12)\n\n# Determine the labels for each tick on the x and y axes\nyticklabels = ['59.0', '60.0', '61.0', '62.0', '63.0', '64.0']\nxticklabels = [\n    '12z', '', '18z', '', 'Apr29', '', '06z', '', '12z', '', '18z', '', 'Apr30',\n    '', '06z', '', '12z', '', '18z', '', 'May01', '', '06z', '', '12z'\n]\n\n# Use the geocat.viz function to set inset axes limits and ticks\ngvutil.set_axes_limits_and_ticks(axin2,\n                                 xlim=[0, 72],\n                                 ylim=[59, 64.5],\n                                 xticks=np.arange(0, 75, 3),\n                                 yticks=np.arange(59, 65),\n                                 xticklabels=xticklabels,\n                                 yticklabels=yticklabels)\n\n# Use the geocat.viz function to add minor ticks\ngvutil.add_major_minor_ticks(axin2, y_minor_per_major=5, labelsize=\"small\")\n\n# Make ticks only show up on bottom, right, and left of inset axis\naxin2.tick_params(bottom=True, left=True, right=True, top=False)\naxin2.tick_params(which='minor', top=False, bottom=False)\n\n# Adjust space between the first and second axes on the plot\nplt.subplots_adjust(hspace=-0.3)\n\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
}