{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h1>19. Contour Plots and Animation</h1>\n",
    "<h2>11/20/23</h2>\n",
    "\n",
    "<h2>19.0 Last Time...</h2>\n",
    "<ul>\n",
    "    <li>You can save a figure to a file using savefig().</li>\n",
    "</ul>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>19.1 Basic Contour Plots</h2>\n",
    "\n",
    "Contour plots work much the same as line plots for things like saving figures to files, etc.\n",
    "\n",
    "The <b>matplotlib.pyplot.contour()</b> function generates a basic contour plot. It typically has four arguments: the first two are the x and y locations of your data values, the third is the 2D array of values to be contoured, and the final argument is an optional parameter that tells you how many contour levels to make."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Locator attempting to generate 3761 ticks ([-41.02, ..., 34.18]), which exceeds Locator.MAXTICKS (1000).\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 192424 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# This is going to be an ongoing example using our\n",
    "# NetCDF file from earlier...\n",
    "\n",
    "import numpy as np\n",
    "import scipy.io as S\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "fileobj = S.netcdf_file('../datasets/air.mon.mean.nc',mode='r')\n",
    "T_time0 = fileobj.variables['air'][0,:,:]\n",
    "T_units = fileobj.variables['air'].units.decode('utf-8')\n",
    "lon = fileobj.variables['lon'][:]\n",
    "lon_units = fileobj.variables['lon'].units.decode('utf-8')\n",
    "lat = fileobj.variables['lat'][:]\n",
    "lat_units = fileobj.variables['lat'].units.decode('utf-8')\n",
    "\n",
    "[lonall,latall] = np.meshgrid(lon,lat)\n",
    "\n",
    "map = plt.contour(lonall,latall,T_time0,5000)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also use the <b>levels</b> keyword to get specific levels where we want contours."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 114040 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "map = plt.contour(lonall,latall,T_time0,levels=[-20,-10,0,10,20])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To make negative contours dashed, set colors to 'k'."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 109444 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "map = plt.contour(lonall,latall,T_time0,colors='k')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By saving this contour plot to a variable, we can then make modifications using functions that ask for a contour map object as input."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<a list of 25 text.Text objects>"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 116460 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# We can add contour labels this way!\n",
    "map = plt.contour(lonall,latall,T_time0,colors='k')\n",
    "plt.clabel(map,fontsize=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sometimes you'll want to fill in the contours! This is done using <b>contourf()</b> instead of <b>contour()</b>. You can also specify a particular colormap using the cmap keyword - there's a list of them here: https://scipy-cookbook.readthedocs.io/items/Matplotlib_Show_colormaps.html."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.colorbar.Colorbar at 0x1284f1290>"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 265188 characters]",
      "text/plain": [
       "<Figure size 500x1500 with 6 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(5,15))\n",
    "plt.subplot(3,1,1)\n",
    "map1=plt.contourf(lonall,latall,T_time0,1000,cmap=plt.cm.flag)\n",
    "plt.colorbar(map1,orientation='horizontal')\n",
    "plt.subplot(3,1,2)\n",
    "map2=plt.contourf(lonall,latall,T_time0,1000,cmap=plt.cm.Paired)\n",
    "plt.colorbar(map2,orientation='horizontal')\n",
    "plt.subplot(3,1,3)\n",
    "map3=plt.contourf(lonall,latall,T_time0,1000,cmap=plt.cm.prism)\n",
    "plt.colorbar(map3,orientation='horizontal')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>19.2 Animations</h2>\n",
    "\n",
    "You can create your own animated images in Python!\n",
    "\n",
    "To begin, you'll create an initial state of a plot (the first frame of the animation), then use a function to \"progress\" to the next frame of the animation, repeat that process, and save the final animation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Start by defining a figure and axes, \n",
    "# then create a line with our old friend plt.plot.\n",
    "\n",
    "\n",
    "\n",
    "# Define a function called init to initialize\n",
    "# the plot!\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# For each frame, create a function that will take an index\n",
    "# and return the desired frame in the animation.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# We'll now create a new runtime configuration that\n",
    "# lets us animate the whole thing!\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>19.3 Take-Home Points...</h2>\n",
    "<ul>\n",
    "    <li>contour() allows you to create customizable contour plots.</li>\n",
    "    <li>contourf() allows you to create customizable filled contour plots.</li>\n",
    "    <li>FuncAnimation allows you to create animations in Python.</li>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.11.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
